原创 如何避免用动态语言的思维写Go代码 | 技术专题第二期征文

发布时间:2021-06-24 11:53:35 浏览 4486 来源:猿笔记 作者:kevinyan

    到写`Go`代码时还是不习惯先定义类型后使用这种习惯。可能写动态语言的程序员在开始用`Go`写代码时都容易犯的一些错误。接下来我们会说几个`PHP`程序员在刚开始用`Go`写程序时几个需要改变的编码习惯和要注意的地方,比如我看一开始有的同学把一些配置信息放在`map[string]string`类型的`Map`里。1后面程序使用的时候再去用键去取值,你在用上面字典里面的数值时还得对他们做类型转换,2**这么做就能避免像上面那样使用`StockNum`前还得把它转成整型的问题了,比如我要用你的方法我还得进去看看你的代码里这个`Map`到底有哪些键。


    由于招聘市场上的‘go’工程师供应不足,我们招聘了很多愿意用‘go’语言进行改造和开发的‘PHP’工程师,但即使换了语言,很多‘PHP’的影子在编码的时候还是能找到的。如果你必须在“如果”这个句子后面加上括号,你就不要说了。这是无知的,gofmt会强行打断你。最大的问题是我以前用的是‘PHP’的数组,但是我写‘Go’代码的时候不习惯先定义类型再用。还有,我写‘PHP’的时候,大概没有养成使用异常的习惯,在返回值里约定了特殊的值来表示错误。所以后来在团队内部做了一次培训,专门分享了如何建立正确的Go编码习惯。以下是当时演讲的节选。其实并不是专门针对‘PHP’程序员的,只是写动态语言的程序员在开始用‘Go’写代码的时候容易犯一些错误。

    ##Go编程注意事项及建议

    接下来我们就来说说` PHP '程序员开始用` go '写程序需要改变的几个编码习惯,以及需要注意的几点。

    # # #尽量用结构切片代替字典

    我们的一些新生特别喜欢在围棋中使用'地图',有时他们会把'地图'切成片。比如我觉得有的同学先把一些配置信息放在` map string] string `type `map '里,如果多的话再把` map '放在切片里,比如这个。

    varconfigMap=[]map[string]string{\t{\t\t"stockNum":"100",\t\t"name":"芒果TV周卡",\t\t"type":"virtual",},}

    当使用后面的程序时,使用键获取值。这个程序当然可以实现,但是你会发现' go '是强类型的,所以在使用上面字典里的值的时候要做类型转换。很多同学会马上说,那我就把‘map’的类型改成‘mapstring]接口{ }’。我只能说你试试看' go '会不会让你在使用的时候做出类型断言。

    这实际上是一种思维的转变,那么我们应该如何用像“go”这样的强类型语言来处理这种情况呢?这就需要我们养成在使用之前定义结构类型的习惯。比如像上面这种情况,我可以先定义一个类型。

    typeProductstruct{\tStockNumint64\tNamestring\tTypestring}varconfigs=[]*Product{\t{\t\tStockNum:100,\t\tName:"芒果TV周卡",\t\tType:"virtual",\t},......}

    * *这样做可以避免如上使用前必须将` StockNum '转换成整数的问题,编辑器还可以进行类型提示,不需要刻意记住Map中的键,也可以避免不小心拼错键而造成bug的尴尬。**

    除此之外,有些人喜欢在返回值中返回` map ',这样不仅会导致上面提到的问题,还会给别人使用带来很大的不便。例如,如果我想使用你的方法,我必须进去看看这个“映射”在你的代码中有什么键。

    所以我们在写` go '代码的时候,其实` map '的利用率比` php '中使用数组的利用率低很多,而且经常使用结构体和结构体进行切片。对于以键为数据标识,以值为数据映射的映射,只需将键改为数据标识,将值改为数据自定义类型。例如,以下类型为“映射”的变量,其“键”是产品的标识,值类型是上面定义的“产品”结构。

    varproductMap=map[int64]*Product{\t123:\t{\t\tStockNum:100,\t\tName:"芒果TV周卡",\t\tType:"virtual",\t},}

    针对这部分的这个问题,我觉得只要记住* *“先按数据打再用”的原则就够了* *。

    在讲了代码中出现率最高的这个问题之后,我们再来讲讲写` go '代码应该注意的一些细节。

    # # #零值陷阱

    未初始化变量的默认值是其类型的零值。应该注意的是,对应于切片'、'映射'、改变'和' *T '类型的零值是'零'。

    这些类型的变量在初始化之前不能直接在程序中使用,在某些情况下可能会导致运行时错误。

    两个常见的运行时错误是:

    -panic:assignmenttoentryinnilmap

    -panic:invalidmemoryaddressornilpointerdereference

    第一个错误是由分配未初始化的“映射”引起的,所以在使用“映射”类型变量之前,请记住用make函数初始化变量。类似于“map”的切片可以通过使用“append”函数向nilslice添加新元素,因为“append”函数将生成新切片并将底层数组分配给底部的切片。

    第二个错误是由对指针“零”的理解引用引起的,指针“零”的零值不等于“*T{}”。因此,指针类型变量应该在使用前用“新”函数初始化。

    还有,前端学生不喜欢接口返回的字段有数据的时候是列表,没有数据的时候是‘Null’,也是切片未初始化造成的。如果在数据库中找不到数据,代码逻辑中就无法执行切片数据的“追加”循环,因此会出现这个问题。这是保持接口字段类型一致的一个非常重要的细节。

    ###使用error返回函数错误

    使用` php '时,函数的错误是通过抛出异常来表达函数遇到的错误,甚至返回值' 0 '和false '(即使编写` php '时也不建议这样做

作者信息

kevinyan [等级:3] Golang工程师
发布了 153 篇专栏 · 获得点赞 1394 · 获得阅读 186554

相关推荐 更多