#1 Go1.13的新特性

寫這篇博客緣由,因?yàn)槲以诰W(wǎng)上搜了很多篇關(guān)于 Go 1.13 的文章,但是很多是直接翻譯官方博客介紹的敏晤,對我們Go開發(fā)經(jīng)驗(yàn)不是很長的人來說,因?yàn)闆]有對應(yīng)大量實(shí)戰(zhàn)經(jīng)驗(yàn)缅茉,看了比較蒙嘴脾,理解不了,就是感覺看不懂為什么需要加這些新特性,所以就自己搜集了很多相關(guān)文章译打,消化理解之后寫出了這篇博客耗拓。Go 1.0發(fā)布到 1.13版本,Go語言本身的語法改動非常少奏司。

一乔询、內(nèi)容

1)Tools 變動
2)標(biāo)準(zhǔn)庫 變動
3)語言 spec 方面變動
4)跨平臺支持

二、Tools

  1. Module

    • 升級到 Go 1.13 后 GOPROXY 和 GOSUMDB 都會有默認(rèn)值韵洋,且默認(rèn)值在國內(nèi)是無法訪問的竿刁,所以為了一切正常,建議大家 go env -w GOPROXY=https://goproxy.cn,direct搪缨,這個(gè)命令是 Go 1.13 新加的食拜,然后 GOSUMDB 就不用改了,因?yàn)?goproxy.cn 支持代理它的默認(rèn)值副编,所以直接就能用负甸。在 Go1.13 之前,GOPROXY=https://goproxy.cn 即可痹届,逗號列表是 Go1.13 才有的呻待。
    • 如果你用了 GOPROXY 或 GOSUMDB,那么你就可能需要了解一下 GONOPROXY队腐、GONOSUDB 還有 GOPRIVATE蚕捉。前兩個(gè)是指定 Go 該怎么處理模塊的下載與校驗(yàn);后三個(gè)是指定 Go 在那些情況下不應(yīng)該根據(jù)前兩個(gè)處理柴淘。所以鱼冀,私有庫的問題可以解決。
    • 關(guān)于 GOPROXY悠就,看看 goproxy.cn 的作者發(fā)布的文章:goproxy.cn - 為中國 Go 語言開發(fā)者量身打造的模塊代理
  2. Command

    • go env 支持 -w 參數(shù)為用戶單獨(dú)設(shè)置環(huán)境變量充易,-u 參數(shù)取消設(shè)置
    • go version 可以查看二進(jìn)制文件的編譯 go 版本
    • go build 的參數(shù) trimpath 可以二進(jìn)制文件中的文件系統(tǒng)路徑以提高 build 效率梗脾;-tags 支持多個(gè)編譯選項(xiàng)
    • go generate 增加 generate build 選項(xiàng)
  3. Compiler Toolchain
    主要改進(jìn)在逃逸分析上更加準(zhǔn)確。因?yàn)楹瘮?shù)棧幀上的變量會隨著函數(shù)調(diào)用結(jié)束而釋放盹靴,所以這可能會導(dǎo)致之前運(yùn)行 OK 的程序出錯(cuò)(比如使用 unsafe 包導(dǎo)致之前誤診斷炸茧,這也是一個(gè)不要使用 unsafe 包的原因)。如果要保持之前的行為可以設(shè)置變量:go build -gcflags=all=-newescape=false

  4. Assembly
    支持 ARM v8.1 引入的原子指令

  5. Gofmt
    支持格式化前面說到的數(shù)字格式稿静。比如:0B1010梭冠,0XabcDEF0O660改备,1.2E3控漠,and 01i 經(jīng)過 fmt 之后得到 0b10100xabcDEF0o660盐捷,1.2e3偶翅,and 1i

  6. godoc
    從主包中移除碉渡,如果要使用聚谁,需要單獨(dú)安裝

    go get golang.org/x/tools/cmd/godoc
    godoc
    
  7. Runtime
    Out of range 的 panic 信息會包含 index 和 cap 的信息。 Defer 的性能提升 30%滞诺,defer的性能消耗可以參考:尼不要逗了:深入理解 Go 語言 defer形导,Runtime 歸還給 OS 的內(nèi)存策略會更激進(jìn)(原文是 aggressive,我理解這里的激進(jìn)的意思大概是有空閑的就還給你习霹,相比之前會保留一段時(shí)間)朵耕。但是由于很多操作系統(tǒng)對內(nèi)存的回收都是惰性的,所以 Runtime 這個(gè)地方的改變可能并不會導(dǎo)致進(jìn)程的實(shí)際使用的物理內(nèi)存顯著減少序愚,除非系統(tǒng)內(nèi)存不足憔披,主動回收。

三爸吮、標(biāo)準(zhǔn)庫 變動

1)errors包(Error Wraping芬膝,包裝錯(cuò)誤)
支持 wrapping,fmt.Errorf 增加 %w 格式符形娇,errors 包增加三個(gè)函數(shù)(Unwrap锰霜、Is、As

  1. errors.Unwrap函數(shù)桐早,原型 func Unwrap(err error) error癣缅,功能:

    • 對 err 進(jìn)行斷言,看它是否實(shí)現(xiàn)了 Unwrap 方法哄酝,如果是友存,調(diào)用它的 Unwrap 方法,否則陶衅,返回 nil屡立。源碼如下
    func Unwrap(err error) error { 
         // 判斷 err 是否實(shí)現(xiàn) Unwrap 函數(shù),也就是是否 是 wrapping error
         u, ok := err.(interface {
                 Unwrap() error
         })
         // 如果不是搀军,返回nil
         if !ok {
                 return nil
         }
         // 否則則調(diào)用該 error 值的Unwrap方法返回被嵌套的error
         return u.Unwrap()
    }
    
  2. errors.Is函數(shù)膨俐,原型 func Is(err, target error) bool,功能:

  • 如果errtarget是同一個(gè)罩句,那么返回true
  • 如果 err 有實(shí)現(xiàn) Is 比較方法焚刺,則使用 err的Is 方法來比較,如果err的Is返回為true门烂,則返回true乳愉,否則繼續(xù) error.Is 的比較
  • 如果err 是一個(gè)wrap error,target也包含在這個(gè)嵌套error鏈中的話,那么也返回true
    很簡單的一個(gè)函數(shù)匾委,要么咱倆相等拖叙,要么err包含target,這兩種情況都返回true赂乐,其余返回false薯鳍。源碼如下
func Is(err, target error) bool {
    if target == nil {
            return err == target
    }

    isComparable := reflectlite.TypeOf(target).Comparable()
    // for循環(huán),把 err 錯(cuò)誤鏈一層層通過剝開挨措,一個(gè)個(gè)比較挖滤,找到就返回true
    for {
            if isComparable && err == target {
                    return true
            }
            // 這里意味著你可以自定義 error 的Is方法,實(shí)現(xiàn)自己的比較代碼
            if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
                    return true
            }
            // 剝開一層浅役,返回被嵌套的err
            if err = Unwrap(err); err == nil {
                    return false
            }
        }
    }
}

為什么需要 Is 函數(shù)斩松?

在 Go 1.13 之前沒有 wapping error 的時(shí)候,我們判斷 error 是不是同一個(gè) error 可以使用如下方法:

if err == os.ErrExist

這樣我們就可以通過判斷來做一些事情觉既。但是有了 Is 方法后惧盹,我們可以進(jìn)行更復(fù)雜的比較了

  1. errors.As 函數(shù),原型 func As(err error, target interface{}) bool瞪讼,功能:
  • 如果 target 為 nil 或者 nil 指針钧椰,或者 不為接口 且 沒有實(shí)現(xiàn) error接口 的話,會 panic
  • 從 err 錯(cuò)誤鏈里找到和 target 相等的并設(shè)置 target 所指向的變量符欠,返回 true嫡霞,否則返回 false
func As(err error, target interface{}) bool {
    // 一些判斷,保證 target 希柿,這里是不能為 nil
    if target == nil {
        panic("errors: target cannot be nil")
    }
    val := reflectlite.ValueOf(target)
    typ := val.Type()
    // 這里確保 target 必須是一個(gè)非 nil 指針
    if typ.Kind() != reflectlite.Ptr || val.IsNil() {
        panic("errors: target must be a non-nil pointer")
    }
    // 這里確保 target 是一個(gè)接口或者實(shí)現(xiàn)了 erorr 接口
    if e := typ.Elem(); e.Kind() != reflectlite.Interface && !e.Implements(errorType) {
        panic("errors: *target must be interface or implement error")
    }
    targetType := typ.Elem()
    for err != nil {
        // 關(guān)鍵部分诊沪,反射判斷是否可以被賦予,如果可以賦予并且返回 true
        if reflectlite.TypeOf(err).AssignableTo(targetType) {
            val.Elem().Set(reflectlite.ValueOf(err))
            return true
        }
        // 這里意味著你可以自定義 error 的As方法曾撤,實(shí)現(xiàn)自己的類型斷言代碼
        if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
            return true
        }
        err = Unwrap(err)
    }
    return false
}

剩下一個(gè) %w 是什么呢端姚?打開源碼

// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error.
//
// If the format specifier includes a %w verb with an error operand,
// the returned error will implement an Unwrap method returning the operand. It is
// invalid to include more than one %w verb or to supply it with an operand
// that does not implement the error interface. The %w verb is otherwise
// a synonym for %v.

// Errorf根據(jù)格式說明符設(shè)置格式,并以
//滿足錯(cuò)誤的值挤悉。
//
//如果格式說明符包含帶有錯(cuò)誤操作數(shù)的%w動詞寄锐,
//返回的錯(cuò)誤將實(shí)現(xiàn)Unwrap方法,返回操作數(shù)尖啡。它是
//包含多個(gè)%w動詞或?yàn)槠涮峁┎僮鲾?shù)無效
//沒有實(shí)現(xiàn)錯(cuò)誤接口的代碼。 %w動詞否則為
//%v的同義詞剩膘。
func Errorf(format string, a ...interface{}) error {
        p := newPrinter()
        p.wrapErrs = true
        p.doPrintf(format, a)
        s := string(p.buf)
        var err error
        if p.wrappedErr == nil {
                err = errors.New(s)
        } else {
                err = &wrapError{s, p.wrappedErr}
        }
        p.free()
        return err
}

type wrapError struct {
        msg string
        err error
}

func (e *wrapError) Error() string {
        return e.msg
}

func (e *wrapError) Unwrap() error {
        return e.err
}

從源碼中我們可以得知是這樣的衅斩,傳入對應(yīng) %w 的值是一個(gè)實(shí)現(xiàn)了 error 接口的值,則返回一個(gè)帶 實(shí)現(xiàn)了Unwrap的error值怠褐,否則 %w 的效果等于 %v畏梆。

2)crypto/ed25519 包
package crypto/ed25519 實(shí)現(xiàn)了之前在 package golang.org/x/crypto/ed25519 中實(shí)現(xiàn)的Ed25519 算法

3)reflect包

reflect標(biāo)準(zhǔn)庫包中將為Value類型添加一個(gè)IsZero方法,用來判斷一個(gè)值是否為零值奠涌。

四宪巨、語言 spec 方面改動

主要集中在這個(gè) Proposal:golang/proposal,主要是一些數(shù)字的表示方面溜畅,包括:

  • 使用 0b/0B 開頭來表示二進(jìn)制數(shù)(賦值給變量之后捏卓,會被轉(zhuǎn)換程十進(jìn)制,還是int慈格、float等類型)
  • 使用 0o/0O(前面是數(shù)字零怠晴,后面是字母o)表示八進(jìn)制數(shù)(如上)
  • 使用0x/0X 開頭來表征十六進(jìn)制數(shù)(如上)
  • 使用 i 來表示復(fù)數(shù)
  • 可使用下劃線 _ 來作為數(shù)字分割

右移位操作的 unsign 限制移除,Proposal: golang/proposal浴捆,移位操作中的右移位將允許為有符號整數(shù)蒜田,在1.13之前的Go 版本,<< 右邊必須為無符號類型確定整數(shù)或者可以表示成uint值的類型不確定值选泻,在1.13之后冲粤,加上了有符號整數(shù)的非負(fù)值,如果是負(fù)正數(shù)页眯,將panic

五梯捕、庫平臺支持

  • AIX:aix平臺支持 cgo
  • Android:兼容 Android Q
  • Darwin:Go 1.13 支持需要macOS 版本 10.11 El Capition 及以上
  • FreeBSD:FreeBSD 11.2及以上
  • Illumos:編譯選項(xiàng) GOOS==illumos 支持
  • NetBSD:支持 NetBSD on ARM64
  • OpenBSD:支持 OpenBSD on ARM64
  • Windows:底層要求 Windows 7

視頻資源

參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末科阎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子忿族,更是在濱河造成了極大的恐慌锣笨,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件道批,死亡現(xiàn)場離奇詭異错英,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)隆豹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門椭岩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人璃赡,你說我怎么就攤上這事判哥。” “怎么了碉考?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵塌计,是天一觀的道長。 經(jīng)常有香客問我侯谁,道長锌仅,這世上最難降的妖魔是什么章钾? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮热芹,結(jié)果婚禮上贱傀,老公的妹妹穿的比我還像新娘。我一直安慰自己伊脓,他們只是感情好府寒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著丽旅,像睡著了一般椰棘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上榄笙,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天邪狞,我揣著相機(jī)與錄音,去河邊找鬼茅撞。 笑死帆卓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的米丘。 我是一名探鬼主播剑令,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拄查!你這毒婦竟也來了吁津?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤堕扶,失蹤者是張志新(化名)和其女友劉穎碍脏,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稍算,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡典尾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了糊探。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钾埂。...
    茶點(diǎn)故事閱讀 38,625評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖科平,靈堂內(nèi)的尸體忽然破棺而出褥紫,到底是詐尸還是另有隱情侧蘸,我是刑警寧澤惜互,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布半醉,位于F島的核電站鹅士,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肝箱。R本人自食惡果不足惜五督,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一匀奏、第九天 我趴在偏房一處隱蔽的房頂上張望矢腻。 院中可真熱鬧门驾,春花似錦、人聲如沸多柑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竣灌。三九已至聂沙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間初嘹,已是汗流浹背及汉。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屯烦,地道東北人坷随。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像驻龟,于是被迫代替她去往敵國和親温眉。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評論 2 348