感觉 golang 比 Java 还难读, 难学

2023-02-23 13:20:57 +08:00
 echoless

要解析的 json, 格式不完美. 比如

[{
"name": "Abyssin",
"price": 500,
"location": "Lviv",
"image": "https://olxua-ring02.akamaized.net/images_slandocomua/476948786_2_1000x700_abissenysh-chempion-fotografii.jpg"
},
{
"name": "Abyssin",
"price": "550",
"location": "Lviv",
"image": "https://olxua-ring10.akamaized.net/images_slandocomua/342850976_3_1000x700_abidetki-koti_rev006.jpg"
}]

price 实际上是个 int 但是有些值是 string. 加 tag 就没啥用了, 只能自己写 UnmarshalJSON

好奇看了一下

json/decode

// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
// If it encounters an Unmarshaler, indirect stops and returns that.
// If decodingNull is true, indirect stops at the first settable pointer so it
// can be set to nil.
func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
	// Issue #24153 indicates that it is generally not a guaranteed property
	// that you may round-trip a reflect.Value by calling Value.Addr().Elem()
	// and expect the value to still be settable for values derived from
	// unexported embedded struct fields.
	//
	// The logic below effectively does this when it first addresses the value
	// (to satisfy possible pointer methods) and continues to dereference
	// subsequent pointers as necessary.
	//
	// After the first round-trip, we set v back to the original value to
	// preserve the original RW flags contained in reflect.Value.
	v0 := v
	haveAddr := false

	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Pointer && v.Type().Name() != "" && v.CanAddr() {
		haveAddr = true
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Pointer && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Pointer) {
				haveAddr = false
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Pointer {
			break
		}

		if decodingNull && v.CanSet() {
			break
		}

		// Prevent infinite loop if v is an interface pointing to its own address:
		//     var v interface{}
		//     v = &v
		if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v {
			v = v.Elem()
			break
		}
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		if v.Type().NumMethod() > 0 && v.CanInterface() {
			if u, ok := v.Interface().(Unmarshaler); ok {
				return u, nil, reflect.Value{}
			}
			if !decodingNull {
				if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
					return nil, u, reflect.Value{}
				}
			}
		}

		if haveAddr {
			v = v0 // restore original value after round-trip Value.Addr().Elem()
			haveAddr = false
		} else {
			v = v.Elem()
		}
	}
	return nil, nil, v
}

感觉 java 感觉清爽很多. java 感觉不需要学, 看看 ArrayList HashMap 这些接口就可以写了,语法也比较简单. golang 真是各种奇技淫巧满天飞.

7390 次点击
所在节点    程序员
65 条回复
Macolor21
2023-02-23 14:21:30 +08:00
@liuxu #6 后面的怎么不截了?

1. 驼峰不允许,写、看 Linux 内核的人,大部分都是 C ,之前的字体可能会大小写不敏感,或者没有等宽字体吧,这是风格问题
2. 局部变量尽量简便,如果 for loop 里面的 index 这种可以简化为 i. 因为它在这里不难理解.
3. 匈牙利命令法:太啰嗦了,没几个人会用
4. 全局变量、函数应该有小写的描述名,适当用下划线区分。一个全局函数叫 `atty()` 也被骂啊,人家要求写成 `get_active_tty()` 还骂这是 Linux 不是 BSD

说白了,就是风格统一的问题,Linux 源码有自己的一套风格( c 语言用户群用的风格),拿其他语言的风格上去提交代码,不是找骂么。你在 Java 里写 get_active_tty() 我也觉得你是傻逼。

第二的问题,Java 里 Foreach 一个集合,也是 collection.foreach(e-> e.printf()); 用 e 或者 ele 代替 elements.

命名风格无法决定语言啰嗦不啰嗦,而是语法糖、特性( Pattern match 、类型推断、类型定义)决定,如果你认为命令风格是 Java 被诟病的原因,只能说你的水平太低,只能当个 reader 和传话太监。

连命令风格都不知道,要么网管转运维的半吊子,要么销售培训转开发的半吊子。
echoless
2023-02-23 14:25:14 +08:00
@zjsxwc 我需要的就是这种
echoless
2023-02-23 14:30:32 +08:00
@MoYi123 他这个命名也不好 应该用单词
a132811
2023-02-23 14:43:21 +08:00
1. 这不是 golang 本身的问题。golang 自带的这个 json 库封装时就没有支持多类型自动转换。
2. 语言风格、习惯其实没有什么好喷的,有人就是喜欢这种简化,有人就是喜欢冗长风格,争论不会任何结果。
3. 不过 golang 有一点好就是源码修改和调试非常的方便。有精力的话,可以给官方提一个 PR
erichen86
2023-02-23 14:44:25 +08:00
python 为什么这么流行,代码看着也挺难受的,感觉还不如 go 看的舒服
yaott2020
2023-02-23 14:44:27 +08:00
@zjsxwc 你可以自己在 github 提个 issue ,或者自定义解析函数,字段多类型可以用 any(interface{})
rrfeng
2023-02-23 14:45:30 +08:00
type IntStr int64

type Model struct {
Price IntStr
}

func (IntStr) Unmarshal(){
...
}
wangsongyan
2023-02-23 14:50:13 +08:00
json.Number
dobelee
2023-02-23 15:03:53 +08:00
value -> v
element -> e

没看出有任何问题。
xiaocaiji111
2023-02-23 15:04:03 +08:00
底层源码是不好看的,不看底层学起来是蛮简单。短变量命名,真的是,有时候源码过长,前面读了后面就忘了啥意思(局部变量用一下的能短则短),还是 java 那样啰嗦点儿好。毕竟是给人看的,看懂最重要。
liuxu
2023-02-23 15:04:43 +08:00
@wuhaoecho 参数就算是 c 也肯定是也要写清楚的,但也不会写成 myFirstCar, mySecondCar 这种,不过 rust 和 golang 这种可以用闭包的,参数用 k,v 简写也正常,闭包本身建议代码不要太复杂

楼上还有一个急的跳脚开始疯狂瞎咬人的我就不 at 了,免得把你这帖子搞的水深火热了,我就是在说 go,c,java 各有各的风格,他连基本的阅读理解能力都没有,就有一些人非要拿 java 的风格往 linux 内核里面搞,截图后面的是 linux 向 bsd 开炮,话题就撤太远了

醉舞经楼半卷书,坐井谈天阔
fgwmlhdkkkw
2023-02-23 15:13:28 +08:00
你自定义一个 Price 类型,不久好了吗?
现实世界就是这么复杂,你换什么语言都要面对的啊?
lxiian
2023-02-23 15:36:25 +08:00
@erichen86 一样 我反正是讨厌 python
echoless
2023-02-23 15:57:42 +08:00
@rrfeng
@fgwmlhdkkkw

```
type IntStr struct {
value int
}

type Model struct {
Name string `json:"name"`
Price IntStr `json:"price"`
Location string `json:"location"`
Image string `json:"image"`
}

func (v *IntStr) UnmarshalJSON(b []byte) (err error) {
s, n := "", float64(0)
if err = json.Unmarshal(b, &s); err == nil {
intVar, _ := strconv.Atoi(s)
v.value = intVar
return
}
if err = json.Unmarshal(b, &n); err == nil {
v.value = int(n)
}
return
}
````

搞定, 还行了. v 友牛皮
realpg
2023-02-23 16:08:26 +08:00
我就搞不懂为啥还要规定变量命名风格。。。
无论啥语言
a132811
2023-02-23 16:24:33 +08:00
@wuhaoecho
没必要用结构体
```
type StrInt int
func (v *StrInt) UnmarshalJSON(b []byte) (err error) {
s, n := "", float64(0)
if err = json.Unmarshal(b, &s); err == nil {
intVar, _ := strconv.Atoi(s)
*v = StrInt(intVar)
return
}
if err = json.Unmarshal(b, &n); err == nil {
*v = StrInt(n)
}
return
}
```
echoless
2023-02-23 16:27:35 +08:00
@a132811

我本来想这个的, golang 水平不够,没搞通.

实际应用来讲 我觉得多数时候没区别 可能有一些性能差异.
falcon05
2023-02-23 16:29:11 +08:00
从动态语言过来的看到这 json 处理感觉有点呆
virusdefender
2023-02-23 16:32:33 +08:00
json.Number 就是来干这个的
vcbal
2023-02-23 16:39:44 +08:00
有没有想过这是你自己的原因?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/918520

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX