Go’s Type System Is An Embarrassment

Go is one of the best tools out there today for heavy lifting and backend code. It’s my go to language when it’s time to bring out the big guns and I enjoy working with it immensely. That being said, its type system is an embarrassment. It’s meant to be clear and comprehensible yet it’s full of awkward surprises.

Lack Of Generics

Most modern type systems have some notion of generics. Generics allow types to interact with other types in a type-safe manner. Go has no support for generics. It’s possible to live without generics by using type assertions (casting) and empty interfaces but these are not checked at compile time. Some built-in functions of Go work with pseudo-generic types (e.g. len(), append()) so the language designers are clearly aware of the problem, and yet this pseudo-generic functionality is not exposed to regular users of the language. The compiler and the type system are there to help the developer; having to cast types back and forth in a statically typed language is just embarrassing.

Confusing Semantics Of Exported Identifiers

Many modern languages provide some mechanism to hide methods and data internal to various compilation units or data structures. This is a good thing; it makes programs more reliable by limiting interfaces exposed by modules and by abstracting away implementation details.

Most programming languages allow this by having a mechanism to expose or hide functions, data fields, and types. Go does this with a twist: it exports the lexical identifier, not program element (e.g. type or function) the identifier represents. As a consequence, if there are no identifiers involved, unexported program elements can leak into other packages. What does this mean? Consider the following example:

1package p1 2 3type hidden struct { 4 Field int 5} 6 7func NewHidden() hidden { 8 return hidden{Field:1337} 9} 10 11package main 12 13import ( 14 "fmt" 15 "p1" 16) 17 18func main () { 19 myHidden := p1.NewHidden() 20 fmt.Println(myHidden.Field) 21 myHidden.Field = 9000 22 fmt.Println(myHidden.Field) 23}

This example will compile and work. Go will have absolutely no problem with this as it’s not the “hidden” type that is unexported, only its identifier. Since the:=operator infers the type of the variable on its left side from the expression on the its right, there are no unexported identifiers involved. People on the golang-nuts mailing list seem to think that this makes the type system “easier to understand and explain” but in my opinion these sort of unintended consequences only make things worse.

In addition, the reflect package does not allow reading or writing struct fields with unexported identifiers (even if the field was reached without using any identifiers) which seems to completely contradict the philosophy of exporting being a strictly lexical concept.

The Verdict

If we were still living in the ’90s or Golang was a hobbyist or experimental programming language, these shortcomings would be acceptable. The year is 2014 however and Golang is heavily backed by Google itself so there is simply no other way to say it: Go’s type system is an embarrassment.

I don’t believe that the lexical exporting issue will ever be resolved, partly because it appears to be an inherent part of the language and partly because I don’t think the designers of the language will ever admit it’s an issue. On the other hand, I’m almost certain that generics will be added at some point, hopefully sooner rather than later. That will make things better.

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java将前端的json数组字符串转换为列表

记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang

Android So动态加载 优雅实现与原理分析

背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我