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

2021-06-25 16:00:45 +08:00
 wowbaby

怎么感觉这语法挺奇怪的, 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

7807 次点击
所在节点    Go 编程语言
45 条回复
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
2021-06-25 17:33:25 +08:00
都什么年代了 还在语言大战。。。
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
2021-06-25 20:41:06 +08:00
给你看一下我后台的一个接口

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

看下 Stephan Wolfram 写的那个基本计算模型(图结构),我觉得可以和图灵机(机械结构)、Lambda Calculus (代数结构)并称了。
oneforallsoft
2021-06-26 10:12:06 +08:00
@no1xsyzy
C 语言你特地标注传指针的话,也是复制结构体
====================
你是 c 菜鸟吗? 连这都搞混?
byte10
2021-06-26 10:26:59 +08:00
@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
2021-06-26 14:03:21 +08:00
@oneforallsoft 明显笔误 “C 语言你不特地标注传指针的话,也是复制结构体”
jorneyr
2021-06-26 16:29:01 +08:00
go + shell 做运维不错,写大量的业务代码 go 写起来比较费劲。
no1xsyzy
2021-06-26 19:41:31 +08:00
@oneforallsoft 少打了个「不」……
C 语言你「不」特地标注传指针的话,也是复制结构体
Akiya
2021-06-26 22:43:16 +08:00
你感觉没错,go 写起来就是很难受,就单从语言来说 C#是写起来最爽的。说 go 写着舒服多半是从 C/C++转的吧

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

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

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

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

© 2021 V2EX