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

都说 go 挺好使的,准备用 go 写几个接口

  •  
  •   wowbaby · 2021-06-25 16:00:45 +08:00 · 7833 次点击
    这是一个创建于 1246 天前的主题,其中的信息可能已经有所发展或是发生改变。

    怎么感觉这语法挺奇怪的, err := xx , _ if err != nil

    var json struct { Value string json:"value" binding:"required" }

    names := []string{"lena", "austin", "foo"}

    视觉上感觉比较乱,可能是年纪来了,学不动了😓

    我刚学 object-c 的时候都没有这种感觉

    像 c#,php,java, js 满屏代码时,看着还是挺有感觉的

    技术栈: 前端,c#,php,object-c

    45 条回复    2021-06-28 21:59:37 +08:00
    CEBBCAT
        1
    CEBBCAT  
       2021-06-25 16:02:09 +08:00 via Android
    那个,可以用 gist 再把代码贴一下吗?
    Itoktsnhc
        2
    Itoktsnhc  
       2021-06-25 16:04:10 +08:00
    习惯了 java c#这类写 go 还是难受的
    Jirajine
        3
    Jirajine  
       2021-06-25 16:06:20 +08:00 via Android   ❤️ 8
    go 好使的是工具链、运行时好使。
    语言上,就不说奇葩语法了,本身就是残废。错误处理、null safety 、泛型都缺失。连个 map 、filter 都没有,光一堆堆的循环都恶心死人。
    wowbaby
        4
    wowbaby  
    OP
       2021-06-25 16:14:11 +08:00
    看来还是得保守一点,毕竟身体要紧
    Rwing
        5
    Rwing  
       2021-06-25 16:14:18 +08:00   ❤️ 2
    go 只是更适合写底层系统而已,你要用他来写业务?头发 --,效率 --,bug ++
    linhongye
        6
    linhongye  
       2021-06-25 16:16:49 +08:00   ❤️ 4
    go 爽的 1 批。
    代码语法等, 非常合适团队协作。
    让人感觉不爽的地方, 我觉得都是防止菜鸟乱写。
    KaynW
        7
    KaynW  
       2021-06-25 16:18:17 +08:00
    if err := xx; err != nil {
    }

    :/doge
    wunonglin
        8
    wunonglin  
       2021-06-25 16:21:30 +08:00   ❤️ 1
    @KaynW #7 _ = xx 天王老子来我也不管 doge
    Vegetable
        9
    Vegetable  
       2021-06-25 16:22:12 +08:00   ❤️ 2
    go 就是难看,代码很乱。他的优势不在这。写业务就是难受。

    他的优点对于只稍微了解过,没把 go 在实际项目中使用过的人,很难体会到。

    现在哪怕是一个很小的项目,在 python 、java 和 go 之间抉择我还是倾向用 go 写,后期部署维护实在太爽了。
    wowbaby
        10
    wowbaby  
    OP
       2021-06-25 16:27:40 +08:00
    @Rwing 因有的地方需要加密, 眼馋 go 的部署和可编译二进制
    Rwing
        11
    Rwing  
       2021-06-25 16:33:34 +08:00
    @wowbaby 现在都容器化了,部署都差不多
    C#也可以编译为单个文件
    https://docs.microsoft.com/en-us/dotnet/core/deploying/single-file
    wowbaby
        12
    wowbaby  
    OP
       2021-06-25 16:46:47 +08:00
    @Rwing c# 客户需求太少了
    bthulu
        13
    bthulu  
       2021-06-25 16:53:06 +08:00   ❤️ 1
    @Vegetable 写业务就是难受为什么你还是倾向用 go 写呢, 是你基本不写业务, 只写基础框架吗?
    youngce
        14
    youngce  
       2021-06-25 16:57:44 +08:00
    @wunonglin #8 哈哈哈哈,是的,一个“_”至少可以减少两行代码 [手动狗头]
    lysS
        15
    lysS  
       2021-06-25 16:59:11 +08:00
    @wunonglin 你这种就没必要写等号了。。。。
    1343EFF
        16
    1343EFF  
       2021-06-25 17:13:14 +08:00
    err!=nil 的难受,社区不是一天两天提了,可惜都被毙掉
    但写后端接口是真的爽,部署又简单
    ylsc633
        17
    ylsc633  
       2021-06-25 17:16:13 +08:00
    用 php go java 都写过业务代码的我来说

    我还是喜欢 go

    快捷 高效 协程的效率特别高

    排错十分友好,代码可读性也很高(除了很多重复的 if err != nil )
    openmm
        18
    openmm  
       2021-06-25 17:25:25 +08:00
    原来不是我写代码的问题 我还说这 go 写完 看起来怎么比我的 c++还乱
    chopper
        19
    chopper  
       2021-06-25 17:26:30 +08:00   ❤️ 1
    为什么上面都说代码乱,难理解,但是维护又超爽。这 2 个不是矛盾的吗 ? 没有:/doge
    index90
        20
    index90  
       2021-06-25 17:27:10 +08:00
    java 里面的数组:double[] myList = {1.9, 2.9, 3.4, 3.5};
    go 里面的“数组”:myList = []float64{1.9, 2.9, 3.4, 3.5}

    貌似 Java 里面习惯类型开头,对齐之后比较好看?
    go 里面习惯变量名开头,对不齐所以不好看?
    Rwing
        21
    Rwing  
       2021-06-25 17:32:38 +08:00
    var app = WebApplication.Create(args);
    app.MapGet("/", async httpContext =>
    {
    await httpContext.Response.WriteAsync("Hello World!");
    });
    app.Run();

    C#这几行就跑起来一个“协程”的 webapi 了,这不爽吗?
    callmedachang
        22
    callmedachang  
       2021-06-25 17:33:25 +08:00
    都什么年代了 还在语言大战。。。
    hingbong
        23
    hingbong  
       2021-06-25 20:28:58 +08:00
    @Rwing
    http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
    writer.Write([]byte("Hello World!"))
    })
    http.ListenAndServe(":8080",nil)
    go 的话就这样
    chenqh
        24
    chenqh  
       2021-06-25 20:41:06 +08:00   ❤️ 1
    给你看一下我后台的一个接口

    ```
    func ApiAdminUserUpdate(c *gin.Context) {
    var err error = func() error {
    user, err := service.GinGetUser(c)
    if err != nil {
    return err
    }
    err = service.CheckUserRoleError(user, enum_data.UserRoleListPlat...)
    if err != nil {
    return err
    }
    d, err := utils.GinRequestD(c)
    if err != nil {
    return err
    }

    local_id, err := lerror.GinDGet(d, "local_id")
    if err != nil {
    return err
    }
    update_at, err := lerror.GinDGet(d, "update_at")
    if err != nil {
    return err
    }
    targetUser, err := service.UserFindByLocalId(local_id)
    if err != nil {
    return err
    }

    err = service.UserCheckUpdatAtStr(targetUser, update_at)
    if err != nil {
    return err
    }

    var fnSendOk = func() {
    lerror.HandlerResponseOk(c)
    }

    var createEvent = func(event, detail string) error {
    LocalId, err := model.RedisIntKey()
    if err != nil {
    return err
    }
    var actionLog = model.MActionLog{
    LocalId: LocalId,
    UserId: user.LocalId,
    Business: enum_data.ActionBusinessUser,
    Event: event,
    Detail: detail,
    Ip: utils.GinRequestIp(c),
    UserAgent: c.Request.UserAgent(),
    RefId: user.LocalId,
    RefTable: "m_user",
    }
    err = model.Db.Create(&actionLog).Error
    return err
    }

    status, flag := d["status"]
    var event string
    var detail string
    if flag {
    // 禁用|启用 用户
    statusI, err := strconv.ParseInt(status, 10, 64)
    if err != nil {
    return err
    }
    event = enum_data.ActionEventUnActive
    detail = enum_data.ActionUserUnactiveFormat(user, targetUser)
    if statusI == int64(1) {
    event = enum_data.ActionEventActive
    detail = enum_data.ActionUserActiveFormat(user, targetUser)
    }
    err = service.UserUpdate(targetUser, gin.H{
    "status": statusI,
    "update_at": time.Now().Unix(),
    })

    if err != nil {
    return err
    }

    err = createEvent(event, detail)
    if err != nil {
    return err
    }

    fnSendOk()
    return nil
    }

    ms_auth_status, flag := d["ms_auth_status"]
    if flag {
    ms_auth_status_i, err := strconv.ParseInt(ms_auth_status, 10, 64)
    if err != nil {
    return err
    }
    event = enum_data.ActionEventMsUnActive
    detail = enum_data.ActionUserMsAuthUnActiveFormat(user, targetUser)

    if ms_auth_status_i == int64(1) {
    event = enum_data.ActionEventMsActive
    detail = enum_data.ActionUserMsAuthActiveFormat(user, targetUser)
    }
    err = service.UserUpdate(targetUser, gin.H{
    "ms_auth_status": ms_auth_status_i,
    "update_at": time.Now().Unix(),
    })
    if err != nil {
    return err
    }
    err = createEvent(event, detail)
    if err != nil {
    return err
    }
    fnSendOk()
    return nil
    }
    name, err := lerror.GinDGet(d, "name")
    if err != nil {
    return err
    }
    nameCount, err := service.UserCount(utils.NewSqlCnd().Eq("name", name).NotEq("local_id", targetUser))
    if err != nil {
    return err
    }

    if nameCount > 1 {
    return lerror.NewMsgError(fmt.Sprintf("用户账号重复 [%s]", name))
    }
    // 更新用户
    nick, err := lerror.GinDGet(d, "nick")
    if err != nil {
    return err
    }
    count, err := service.UserCount(utils.NewSqlCnd().Eq("nick", nick).NotEq("local_id", targetUser))
    if err != nil {
    return err
    }
    if count > 0 {
    return lerror.NewMsgError(fmt.Sprintf("昵称重复 [%s]", nick))
    }

    ms_auth_secret, err := lerror.GinDGet(d, "ms_auth_secret")
    if err != nil {
    return err
    }

    secret, err := lerror.GinDGet(d, "secret")
    if err != nil {
    return err
    }
    update_d := gin.H{
    "nick": nick,
    "ms_auth_secret": ms_auth_secret,
    "secret": secret,
    "update_at": time.Now().Unix(),
    }
    err = service.UserUpdate(targetUser, update_d)
    if err != nil {
    return err
    }

    return nil
    }()
    if err != nil {
    logging.Info("err:%s", err)
    lerror.HandlerResponseError(c, err)
    return
    }
    }



    ```
    crclz
        25
    crclz  
       2021-06-25 20:51:42 +08:00   ❤️ 1
    go 确实是缺胳膊少腿。

    你说 go 可以防止菜鸟乱写,这没有错。但是 java 、C#可以通过代码分析、代码检查限制菜鸟的自由度,一样好使。对于 C#,微软已经提供了语法树结构的 api,普通人都可以写一个代码检查工具,并集成到 visual studio,或者在编译时触发不同的 warning/error 等级。

    我认为 go 最恶心的地方有两处:
    1. 错误处理。go 标准库的错误处理的设计其实是在挑衅 C#、java 、kotlin 、python 的标准库的错误处理设计。毫无疑问,go 的设计是错误的。Go 语言的错误处理机制是一个优秀的设计吗? - Crucialize 的回答 - 知乎
    https://www.zhihu.com/question/27158146/answer/1938195485
    2. 指针需要加“*”号。在面向对象语言中,传递指针是常见的应用场景,copy 对象是鲜有的情况。但是 go 里面却默认 copy 对象,纯粹恶心人。对于需要性能的场景可以理解,但是 C#也有 struct,所以 go 完败。
    yin1999
        26
    yin1999  
       2021-06-25 21:24:16 +08:00   ❤️ 1
    @crclz 关于 copy 对象这块,我觉得问题并没有那么大。Go 语言选择了保留指针的设计,如果你不打算拷贝结构体,可以选择传递指针(除了不能指针运算,其他的和 C/C++是保持完全一致的)。而且 Go 语言本身就不是严格意义上的面向对象的语言,把一些面向对象的观点强加在另一种语言上并没有那么合适(不同的语言总有不同的特点)。
    lanjz
        27
    lanjz  
       2021-06-25 21:43:01 +08:00
    @chenqh #24 看到没忍住就笑了
    FightPig
        28
    FightPig  
       2021-06-25 21:52:39 +08:00
    我选 vlang,就是没生态
    EPr2hh6LADQWqRVH
        29
    EPr2hh6LADQWqRVH  
       2021-06-25 21:54:31 +08:00 via Android
    毕竟 21 世纪 PHP
    BeautifulSoap
        30
    BeautifulSoap  
       2021-06-25 22:45:11 +08:00 via Android
    go 的这错误处理是真的属于那种看得乱写起来啰嗦,但是真的跑起来很爽的设计(前提是别总是直接 _ = err )
    对于 go 的错误处理,目前不满主要还是在于错误不带调用栈,出个错一层层传上来根本不知道哪里的错误,所以必须要一个支持调用栈的第三方包。然后现在错误的那个 wrap 和 unwarp 的机制实在是在搞无线套娃,系统复杂了你根本不知道调用的函数返回的错误有没有 wrap 了调用栈,所以不管三七二十一对所有返回的错误总之都 wrap 下成了基本操作,导致最终上层拿到的错误里面是各种无线套娃后的错误,根本不知道该 unwrap 哪层的错误
    chenqh
        31
    chenqh  
       2021-06-25 23:14:21 +08:00
    @lanjz 网上还说 golang 有 py 80%的开发速度,感觉就是在吹牛
    awing
        32
    awing  
       2021-06-25 23:35:25 +08:00
    脱离应用场景,说什么好用,什么不好用,就是在耍流氓( X
    morty0
        33
    morty0  
       2021-06-26 00:46:07 +08:00
    关于 go 的异常处理可以看看这篇
    https://blog.golang.org/errors-are-values
    no1xsyzy
        34
    no1xsyzy  
       2021-06-26 01:15:20 +08:00
    @crclz C 语言你特地标注传指针的话,也是复制结构体,这个蛋疼一脉相承
    需要搞指针、传引用这一点其实暗示了面向对象这想法本身有问题:它的封装方式希望把所有的状态和状态变化方式归纳到一个树形结构里去,所有的状态在树里,所有的状态变化方式是仅上下传递。这其实是不可能的。由此导致人们创造了一堆 workaround 去解决这个问题,比如 MVC 。

    看下 Stephan Wolfram 写的那个基本计算模型(图结构),我觉得可以和图灵机(机械结构)、Lambda Calculus (代数结构)并称了。
    oneforallsoft
        35
    oneforallsoft  
       2021-06-26 10:12:06 +08:00
    @no1xsyzy
    C 语言你特地标注传指针的话,也是复制结构体
    ====================
    你是 c 菜鸟吗? 连这都搞混?
    byte10
        36
    byte10  
       2021-06-26 10:26:59 +08:00   ❤️ 1
    @Jirajine @linhongye 你们 2 个可以 PK 了哈哈。 我觉得凡是防止菜鸟乱写的语言 都是比较底层的,比如 C,C++ ,都不适合写业务,餐桌鸡都是用来写业务的。不然为啥 java 那么多菜鸡都可以去学习,这是不可避免的。团队还是菜鸡多的。
    @Vegetable 是不是少了一个 nodejs,js 更嗨,可以裸奔,可以不受任何约束哈哈,代码格式化下就行了。
    @ylsc633 nodejs 呢?协程并不是 go 对比其他语言的亮点,别的语言也有。并发模型中还有 actor 模型,也非常的 6 。vert.x 搞分布式系统也贼 6 。
    @1343EFF 因为 go 的框架还是面向过程的,等面向对象的出来,你就不喜欢了。nodejs 也是挺不错的,koa 框架写接口非常的快。
    @Rwing 嗯,你说的对,很多人还以为 go 协程很 6,其他语言也很强的。kotlin 的实现好像比他也好。
    Damenly1
        37
    Damenly1  
       2021-06-26 14:03:21 +08:00
    @oneforallsoft 明显笔误 “C 语言你不特地标注传指针的话,也是复制结构体”
    jorneyr
        38
    jorneyr  
       2021-06-26 16:29:01 +08:00
    go + shell 做运维不错,写大量的业务代码 go 写起来比较费劲。
    no1xsyzy
        39
    no1xsyzy  
       2021-06-26 19:41:31 +08:00
    @oneforallsoft 少打了个「不」……
    C 语言你「不」特地标注传指针的话,也是复制结构体
    Akiya
        40
    Akiya  
       2021-06-26 22:43:16 +08:00 via iPhone
    你感觉没错,go 写起来就是很难受,就单从语言来说 C#是写起来最爽的。说 go 写着舒服多半是从 C/C++转的吧
    xcstream
        41
    xcstream  
       2021-06-27 00:23:21 +08:00
    部署简单 , 写起来不算方便
    qq1340691923
        42
    qq1340691923  
       2021-06-28 10:54:15 +08:00
    @chopper 维护是指部署维护爽,不是指维护代码
    back0893
        43
    back0893  
       2021-06-28 14:00:20 +08:00
    习惯就好.
    stach
        44
    stach  
       2021-06-28 16:47:48 +08:00
    - go 的语法确实没有什么亮点, 甚至是糟糕, 写业务不比 python, php, java 等语言有优势.
    - go 的优势在于 `协程` 做的好, 标准库完善, 且性能好, 因此, 菜鸟写出来的代码性能也不会太差.
    - go 的出发点是替代 c++, 针对性解决了 c++ 的痛点, 例如编译速度, 语法指针过于复杂, 等等.

    没有完美的语言, 我个人常用 python, go 两种语言.
    XhstormR02
        45
    XhstormR02  
       2021-06-28 21:59:37 +08:00 via Android
    语言路线:c -> java -> kotlin -> rust
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2693 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 12:16 · PVG 20:16 · LAX 04:16 · JFK 07:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.