V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
only0jac
V2EX  ›  Go 编程语言

好厉害的 Go,跟 py 一比,简直了

  •  
  •   only0jac · 2016-12-29 23:05:19 +08:00 · 10606 次点击
    这是一个创建于 2917 天前的主题,其中的信息可能已经有所发展或是发生改变。

    就冲 golang 可以生成二进制单文件这一点,部署方便,想试试

    拿 beego 练个手,用了它的 httplib 模块,其中, request 后有个直接将结果转换成 json 的,原文如下:

    解析为 JSON 结构, req.ToJSON(&result) 方法

    返回结构直接解析为 JSON 格式,解析到 result 对象中

    我!以!为!这是和 py 的 json.loads()一样,心理窃喜,接下来……

    我传了个 string ,没数据,传个空接口,没数据。。。。。

    看了下源码,是直接调用的 json.Unmarshal(data, v),属于 golang 自带的库,可我一搜……

    竟然发现,需要提前定义 json 的结构???而且字段首字母必须大写???不然还得声明???

    WTF

    beego 的 request 可以返回 string ,像 py 的 requests.get(url).text ,但是我不想这样,我想 json.loads(requests.get(url).text)

    我就是想获取个 json 而已,能不能不要这么折腾人?

    88 条回复    2017-02-12 17:24:36 +08:00
    Allianzcortex
        1
    Allianzcortex  
       2016-12-29 23:10:07 +08:00   ❤️ 1
    Go 是静态语言,在解析 JSON 上是没有 Python 有优势的
    phrack
        2
    phrack  
       2016-12-29 23:26:29 +08:00 via Android
    难道你第一门语言是 py 不是 c ´・ᴗ・`
    icedx
        3
    icedx  
       2016-12-29 23:33:09 +08:00   ❤️ 1
    其实就是一个入乡随俗的道理
    顺便 Python 是鸭子类型
    这是没有这个特性的语言比不了的
    choury
        4
    choury  
       2016-12-29 23:33:15 +08:00 via Android
    你是没用过 C , java 这些吧
    scnace
        5
    scnace  
       2016-12-29 23:42:38 +08:00
    试试解析到 map 里面(嘿嘿嘿
    TheCure
        6
    TheCure  
       2016-12-29 23:45:02 +08:00
    simplejson
    defia
        7
    defia  
       2016-12-29 23:45:13 +08:00
    可以 map[string]interface{}吧
    gouchaoer
        8
    gouchaoer  
       2016-12-29 23:45:57 +08:00 via Android
    静态语言里不如 rust
    nicevar
        9
    nicevar  
       2016-12-29 23:47:27 +08:00
    哈哈,如果让你用 c 来处理 json 会不会上吊了
    only0jac
        10
    only0jac  
    OP
       2016-12-29 23:51:35 +08:00 via Android
    @phrack 其实第一门是 basic

    @choury 用过 c#,记得 java 也不用先自己声明 json 字段啊

    @scnace
    @defia 能否细说一下?


    @callofmx 这个是 beego 自带的,没用其他库,要是我自己写的话就去找方便的了

    @nicevar 还真没试过
    Tyanboot
        11
    Tyanboot  
       2016-12-29 23:59:14 +08:00 via Android
    scnace
        12
    scnace  
       2016-12-30 00:02:12 +08:00   ❤️ 1
    就是不用`struct`的形式了 而是采用`map[string]interface{}`的形式呀。然后`Unmarshal`之后 map 的 key(string)就是 json 的 key map 的 value 就是 json 的 value 惹 。 但是 我还是建议解析到 struct 的 代码可维护性会强很多(不要问我怎么知道的
    Tyanboot
        13
    Tyanboot  
       2016-12-30 00:03:41 +08:00 via Android   ❤️ 1
    @Tyanboot 不好意思手抖按到回复了…
    我觉得看库的实现吧
    c#有个 NewtonJson 。也是需要先有个定义好的类来做载体,才能解析到定义好的类的实例上。也就是需要先声明 JSON 的字段格式。

    但是 c++是有个 jsoncpp 的库,不需要定义 JSON 的格式,用起来要舒服不少。
    limhiaoing
        15
    limhiaoing  
       2016-12-30 00:20:07 +08:00 via iPhone   ❤️ 1
    json 反序列化成 struct 难道不是很方便的功能吗,而且一般不会强制要求必须定义结构体。这个能力一般都是用反射来实现的,楼上说的 C++现阶段要实现并不容易,可能至少需要静态反射标准化后才能做到。 rust 之前用过一个 json 库也有这个特性,不知道是怎么实现的。
    soli
        16
    soli  
       2016-12-30 00:27:15 +08:00
    知足吧。

    别说 JSON ,你用 C 拼个字符串试试。
    eyp82
        17
    eyp82  
       2016-12-30 00:29:46 +08:00
    python 党笑而不语
    reus
        18
    reus  
       2016-12-30 00:32:44 +08:00   ❤️ 2
    定义一个结构体很麻烦吗?

    var data struct {
    // xxx
    }

    定义变量的时候就可以定义 struct ,或者说 go 的 struct 可以是匿名的

    在静态类型语言里, go 处理 json 是最方便的了,因为有 reflection

    别用什么 map[string]interface{},处理嵌套的结构你就知道了

    var data struct {
    List []struct{
    Info struct {
    // xxx
    }
    }
    }

    你用 map[string]interface{}试试?类型转换烦死你。

    再说回来,想学 go 就直接学标准库,别像学 py 一样,上来就框架。 go 的标准库功能比 py 的强得多,根本不需要 beego 这种东西。
    kkk330
        19
    kkk330  
       2016-12-30 00:35:33 +08:00   ❤️ 1
    - 函数签名是 json.Unmarshal(data []byte , v interface{})
    - 也就是说 lz 你想简单点就直接

    ```go
    data := []byte("{"a":"a", "b": 1}")
    var v interface{}
    json.Unmarshal(data , v)
    fmt.Println(v)
    ```
    jsq2627
        20
    jsq2627  
       2016-12-30 00:35:52 +08:00 via iPhone
    @Tyanboot 你说的只是 newtonjson 的一种早期强类型用法。现在是可以反序列化成 dynamic 类型,或者 jtoken 类型配合 linq 很方便。
    虽然我没用过 go 但我觉得一定存在一种不需要预先定义 schema 的使用方式的。
    est
        21
    est  
       2016-12-30 00:36:51 +08:00
    map[interface{}]interface{} 大法好。

    另外静态语言里搞一个 [1, "1", None, {1: 2, None: 0, 2: 3}] 好像是不可能实现的。。
    sagaxu
        22
    sagaxu  
       2016-12-30 00:42:55 +08:00 via Android
    @est JAVA 可以用 list of Object
    est
        23
    est  
       2016-12-30 00:53:27 +08:00
    @sagaxu 一个方法只接受普通 array 作为参数怎么办。。。
    orvice
        24
    orvice  
       2016-12-30 01:08:38 +08:00
    首字母大写是因为不大写 json 包就获取不到成员的值了。
    orvice
        25
    orvice  
       2016-12-30 01:13:43 +08:00
    也不一定要定义结构体啦,也可以用 map[string]interface{} 但是类型转换会烦死人、。。
    sagaxu
        26
    sagaxu  
       2016-12-30 01:44:28 +08:00
    @est Object[]
    Reficul
        27
    Reficul  
       2016-12-30 02:01:32 +08:00 via Android   ❤️ 1
    等到接手一个老项目,不知道传过来的 JSON 里面元素有哪些的时候,就能感叹动态一时爽的道理了
    yegle
        28
    yegle  
       2016-12-30 03:08:20 +08:00
    @est
    可以实现,就是麻烦一点。你需要用一个 struct 来 hold 所有可能的值(类似 C union ),然后自己写 marshal/unmarshal 。
    vizee
        29
    vizee  
       2016-12-30 03:24:07 +08:00
    好的, 那就不用
    ericls
        30
    ericls  
       2016-12-30 03:46:25 +08:00 via iPhone
    我喜欢了很多的语言 是不是不够上道
    keysona
        31
    keysona  
       2016-12-30 04:12:24 +08:00
    更有有点吧。

    看你是要性能还是轻松了。

    大部分情况下我会选择轻松。
    huodon
        32
    huodon  
       2016-12-30 06:19:30 +08:00 via Android   ❤️ 1
    底子太差。。。
    20015jjw
        33
    20015jjw  
       2016-12-30 07:24:27 +08:00 via Android
    @huodon 这都能黑?
    jingniao
        34
    jingniao  
       2016-12-30 07:41:03 +08:00 via Android
    静态偏底层的处理,意味着 python 隐藏的的一些细节, go 中你得自己来处理。
    昨天学习 go ,重写一个 python 模块,代码量至少两倍。
    assassinpig
        35
    assassinpig  
       2016-12-30 07:56:51 +08:00 via Android
    Go 不适合 LZ
    MushishiXian
        36
    MushishiXian  
       2016-12-30 08:09:30 +08:00
    .....这有啥好吐槽的,你怎么不说性能
    only0jac
        37
    only0jac  
    OP
       2016-12-30 08:33:36 +08:00 via Android
    @messyidea 感谢,这篇很详细,回去仔细看看

    @limhiaoing 方便吗,如果返回的 json 有 100 个字段,难道我 struct 里也需要跟着定义 100 个吗(假设这 100 个字段都有用)
    only0jac
        38
    only0jac  
    OP
       2016-12-30 08:37:42 +08:00 via Android
    @kkk330
    var v interface{}
    json.Unmarshal(data , v)
    fmt.Println(v)
    这种定义空接口是不会输出任何东西的
    jeffersonpig
        39
    jeffersonpig  
       2016-12-30 08:43:42 +08:00
    最不能忍的是 go 强制{}的对齐方式, WTF
    limhiaoing
        40
    limhiaoing  
       2016-12-30 08:45:34 +08:00 via iPhone
    @only0jac
    你非要着眼于不方便的地方不用就是了!
    jsou
        41
    jsou  
       2016-12-30 08:47:02 +08:00
    @only0jac
    既然你 json 能定义 100 个字段,为什么就不能在 go 里定义一个包含 100 个字段的结构体呢
    only0jac
        42
    only0jac  
    OP
       2016-12-30 08:59:54 +08:00 via Android
    @jsou 谢谢
    kingddc314
        43
    kingddc314  
       2016-12-30 09:08:51 +08:00 via Android
    静态语言就这样,要习惯,至少 Go 还有反射。当初 C/C++拼装解析 JSON 那才是一个痛苦,只是后来的 C++11 特性才好一丁点
    ry_wang
        44
    ry_wang  
       2016-12-30 09:21:06 +08:00   ❤️ 1
    不想定义结构体还想用着简单, https://github.com/tidwall/gjson 啊。
    Immortal
        45
    Immortal  
       2016-12-30 09:26:50 +08:00
    静态语言都这样,不知道吐槽点在哪里. 既然选择了静态语言 势必要牺牲一些便携性 多写两行代码 空间换时间
    而且看标题我以为是来夸 go 的...
    pubby
        46
    pubby  
       2016-12-30 09:41:53 +08:00 via Android
    我猜应该有工具能输入复杂样本自动生成结构定义的

    有些比较麻烦的地方是
    type JobTime time.Time

    必须自己实现一遍 Marshal/Unmarshal
    Citrus
        47
    Citrus  
       2016-12-30 09:48:25 +08:00
    前几楼不要乱黑啊,虽然个人不喜欢 Java ,但是 Java 反序列化 Json 还真不需要定义啊,而且有很多方法。
    1. 直接反序列化成 Map<String, String> ,最粗暴,但是对某些 Json 结构支持不好
    2. 直接反序列化成 JSONObject ,完美方案
    pubby
        48
    pubby  
       2016-12-30 09:53:44 +08:00
    @Citrus 还是 Gson 之类的用起来更清晰一些
    only0jac
        49
    only0jac  
    OP
       2016-12-30 10:04:54 +08:00
    @ry_wang 多谢,真不错
    kkk330
        50
    kkk330  
       2016-12-30 10:08:01 +08:00   ❤️ 1
    @only0jac 我的错
    var v interface{}
    json.Unmarshal(data , &v)
    fmt.Println(v)

    应该传地址
    mengzhuo
        51
    mengzhuo  
       2016-12-30 10:17:08 +08:00
    首先,静态语言就是这样的……
    100 项可以用 go generate 自动生成,首字母大写可以用
    type A struct {

    ST `json:"st"`
    }
    likexian
        52
    likexian  
       2016-12-30 10:20:59 +08:00   ❤️ 1
    https://github.com/likexian/simplejson-go#example

    楼主看这里, load json 那段
    mengzhuo
        53
    mengzhuo  
       2016-12-30 10:25:12 +08:00   ❤️ 1
    而且不一定要定义完 result ,你需要什么数据,就定义什么好了

    比如

    {
    "A": 1,
    "B": 2,
    "C": "OK",
    }

    你的处理函数只需要里面的 C 的话,

    type Result struct {
    C string
    json.RawMessage
    }


    具体请看官方标准库, https://golang.org/pkg/encoding/json/#example_RawMessage
    only0jac
        54
    only0jac  
    OP
       2016-12-30 10:32:21 +08:00 via Android
    @likexian 多谢,很方便,你博客简介亮了^_^
    sampeng
        55
    sampeng  
       2016-12-30 10:37:36 +08:00
    我觉得这是是语言的哲学决定的。
    golang 的开发者觉得,开发语言不能有歧义,如果是不需要定义结构体。真的,在项目里面看到各种 json 对象乱飞,都不知道哪来得时候就很痛苦。
    定义结构体最大的好处是语言自文档化,光看代码就能了解整个逻辑。现在特别反感在代码里绕圈子的。简直是折磨
    想想 golang 连方法重载这种特性都没有就能理解了。。
    tairan2006
        56
    tairan2006  
       2016-12-30 10:37:59 +08:00 via Android
    楼主你没写过静态语言么… 实际上可以用匿名 struct 的,不一定要预定义
    dreamtrail
        57
    dreamtrail  
       2016-12-30 11:02:25 +08:00   ❤️ 1
    其实静态语言也没那么可怕,你只要写一次,以后直接复制代码修改一下就行了,虽然还是比不上脚本但也不是想象的那么麻烦。
    gamexg
        58
    gamexg  
       2016-12-30 11:56:40 +08:00   ❤️ 2
    python 转 go

    go 的 json 也是可以不先定义结构,但是每次使用时的检查和转换烦死人,静态类型语言都有这个问题。
    不过现在觉得这是一个好的特征,只用定义好结构,然后 json 解析到结构一次就能够确定 json 符合预期,之后就不用每个字段都检查一次了。

    另外搜索 generate go struct from json ,直接有在线网站提供根据 json 自动生成 go 结构,直接用即可。


    python 时就已经是动态一时爽,重构火葬场了。
    每次接口修改字段都需要检查很多地方,悲剧的是 ide 搜索不是找到不相关的就是漏下一些。

    静态语言 ide 可以轻松找出来哪些地方引用了接口的结构。
    只要确定结构定义处改了,即使有忘了的地方编译时自动报错。
    magicdawn
        59
    magicdawn  
       2016-12-30 12:00:59 +08:00
    C# 都有 dynamic
    mathgl
        60
    mathgl  
       2016-12-30 12:02:39 +08:00
    @phrack 有部分人第一门语言是 basic pascal,
    mathgl
        61
    mathgl  
       2016-12-30 12:03:21 +08:00
    @Tyanboot c++现在比较好的显然是 rapidjson
    ispinfx
        62
    ispinfx  
       2016-12-30 12:07:48 +08:00 via iPhone
    人生苦短 我用 Python
    moliliang
        63
    moliliang  
       2016-12-30 12:10:26 +08:00
    golang 大法好,无需 bb ,,,哈哈哈
    boneyao
        64
    boneyao  
       2016-12-30 12:26:47 +08:00
    定义一个结构体很麻烦吗?
    定义一个不麻烦,但是定义 100 个的时候感觉快崩溃了。
    lijiac
        65
    lijiac  
       2016-12-30 12:28:14 +08:00
    乍看标题以为楼主要黑我 python ,正准备撸起袖子大干一场,结果...
    zhiyong
        66
    zhiyong  
       2016-12-30 12:54:45 +08:00   ❤️ 1
    看看 github.com/tidwall/gjson 这个库,或许能帮到你!
    shyling
        67
    shyling  
       2016-12-30 12:55:34 +08:00
    我知道楼主喜欢那种 JsonObject.getXX("name").getYY("name")那种 0v0
    rrfeng
        68
    rrfeng  
       2016-12-30 12:57:37 +08:00
    有这样的 json 库。

    但是怎么说呢……
    coldwinds
        69
    coldwinds  
       2016-12-30 13:30:28 +08:00 via Android
    入乡随俗
    levn
        70
    levn  
       2016-12-30 13:36:42 +08:00
    先在静态语言里实现一个动态语言……然后……
    fcfangcc
        71
    fcfangcc  
       2016-12-30 13:45:12 +08:00   ❤️ 1
    json.loads(requests.get(url).text) 可以 requests.get(url).json()
    woniuge
        72
    woniuge  
       2016-12-30 13:48:05 +08:00   ❤️ 2
    Immortal
        73
    Immortal  
       2016-12-30 13:56:34 +08:00   ❤️ 1
    再说一句
    不需要定义结构体的用法
    map[string]interface{}

    还有 golang 的常用 json 库 上面说的 gjosn 还有一个 simplejson 前者性能更高一些
    能直接 get json 里的字段
    fuyufjh
        74
    fuyufjh  
       2016-12-30 14:04:57 +08:00   ❤️ 2
    如果结构已知, dict 毕竟要查找,效率和 struct 不能比的。作为一门可以编译到二进制的强类型语言,当然是 struct

    如果结构不定,就要传 map[string]interface{}进去

    不带你这样不会用就黑的。。
    9
        75
    9  
       2016-12-30 14:13:39 +08:00
    @only0jac lz 可以看看跟你类似的吐槽 https://www.v2ex.com/t/98585
    taowen
        76
    taowen  
       2016-12-30 15:43:33 +08:00
    可以看一下我写的 jsoniter http://jsoniter.com/java-features.html 解析各种 json 应该要方便很多了
    这个是 java 版本的文档, golang 版本的稍后更新
    gouchaoer
        77
    gouchaoer  
       2016-12-30 16:57:51 +08:00 via Android
    易语言可以生成二进制呢
    qwer1234asdf
        78
    qwer1234asdf  
       2016-12-30 17:00:33 +08:00
    最蛋疼的是改数据结构, struct 越改越乱。。。
    only0jac
        79
    only0jac  
    OP
       2016-12-30 17:32:09 +08:00
    @taowen 404 了
    @fuyufjh 谢谢,不是黑
    @Immortal 多谢
    @woniuge 很方便的工具,谢谢
    @zhiyong 这库很好,不过前几楼的同学说 golang 自带的库很不错,我先把官方库库搞明白了,再去用第三方,谢谢
    @gamexg 谢谢,受教了
    a7a2
        80
    a7a2  
       2016-12-30 17:34:52 +08:00
    写吧 多写点 以后就可以复制粘贴了 那些什么编程语言都用过的人 都是复制粘贴的
    程序员不可能同时专注几种语言的 写 java 三年 然后 python 三年 然后 go 三年 这个时候忘掉了 Java 的了。。。
    incompatible
        81
    incompatible  
       2016-12-30 17:38:13 +08:00 via iPhone
    @est 搞出「 [1, "1", None, {1: 2, None: 0, 2: 3}] 」这种非标 json 的必要性是?
    billlee
        82
    billlee  
       2016-12-30 20:51:50 +08:00
    只是不同的设计模式而已,就像 Java 的 org.json 与 Jackson 的区别。
    est
        83
    est  
       2016-12-30 21:47:02 +08:00
    @incompatible 只是说兼容性而已。

    py 在运行时可以随意改 json 解析。。。也算个优点吧
    pathbox
        84
    pathbox  
       2016-12-31 11:39:09 +08:00
    静态语言和动态语言的区别。你静态语言不过关啊 lz
    mengskysama
        85
    mengskysama  
       2017-01-01 01:57:46 +08:00
    用 go 写 api 真心累,特别是操作大量 json 的时候不如 node 和 py 灵活。用了十来个框架下来最喜欢的是 koa ,性能开发效率兼备,至于部署的话...都不是个问题。
    only0jac
        86
    only0jac  
    OP
       2017-01-01 09:53:25 +08:00 via Android
    @mengskysama go 部署简单啊,最后只有一个二进制文件, py 部署还得装环境,装虚拟空间, node 没用过,不知道怎么部署
    reyoung1110
        87
    reyoung1110  
       2017-01-01 20:49:21 +08:00
    freestyle
        88
    freestyle  
       2017-02-12 17:24:36 +08:00
    确实,Python 解析 json 比 GO 方便多了

    golang 得定义好结构体, 否则用 map[string]interface{} 的话要用的时候每一层都得类型转换.不过 JSON 格式本来就比较灵活,嵌套的话要写一大把结构体-_-
    response.Result.(map[string]interface{})["files"].([]interface{})[0].(map[string]interface{})["path"].(string)

    另外大写是 go 的机制,大写的才能访问到, 可以用结构体注解表示序列化后的小写 key
    type Aria2JsonRPCReq struct {
    Method string `json:"method"`
    Jsonrpc string `json:"jsonrpc"`
    Id string `json:"id"`
    Params []interface{} `json:"params"`
    }
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3050 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 13:41 · PVG 21:41 · LAX 05:41 · JFK 08:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.