亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

go:識別“標志重新定義”的包

go:識別“標志重新定義”的包

Go
慕標琳琳 2023-02-06 18:59:13
如果一個標志被重新定義,go 只會告訴標志被重新定義的地方之一。有沒有辦法確定另一個標志的定義位置?舉個例子,看下面的程序。在此處foo.go,定義了第一個標志。假設我試圖在 package 中添加一個具有相同名稱的標志main,go panic 告訴我該標志已經定義(因為 packagefoo首先被初始化)并且我正在 package 中重新定義它main。這是一個簡單的例子,但在一個大型代碼庫中,標志可以在導入的庫中定義,很難找出標志是在哪里第一次定義的。有什么辦法可以找出來嗎?package mainimport (    "flag"    "play.ground/foo")func main() {    var tf string    flag.StringVar(&tf, "tf", "", "")    foo.Bar()}-- go.mod --module play.ground-- foo/foo.go --package fooimport (    "flag"    "fmt")func init() {    var tf string    flag.StringVar(&tf, "tf", "", "")}func Bar() {    fmt.Println("This function lives in an another file!")}恐慌:/tmpfs/play flag redefined: tfpanic: /tmpfs/play flag redefined: tfgoroutine 1 [running]:flag.(*FlagSet).Var(0xc0000960c0, {0x4c3148, 0xc0000980a0}, {0x4a2642, 0x2}, {0x0, 0x0})    /usr/local/go-faketime/src/flag/flag.go:980 +0x2f9flag.StringVar(...)    /usr/local/go-faketime/src/flag/flag.go:851main.main()    /tmp/sandbox3734065722/prog.go:11 +0x7dProgram exited.游樂場:https ://go.dev/play/p/jsmMcnEO2hy
查看完整描述

1 回答

?
紅顏莎娜

TA貢獻1842條經驗 獲得超13個贊

正如上面評論中所寫,沒有工具可以做到這一點。


但是您可以使用一個簡單的技巧來找出答案。


你想注冊一個標志,但你不能,因為它已經在其他地方(未知位置)注冊過。


如果可以先注冊,則報錯時會報當前注冊的地方。


怎么做?創建一個注冊此標志的包:


package first


import "flag"


func init() {

    flag.String("tf", "", "")

}

然后像這樣在你的包中首先導入這個包main:


package main


import _ "play.gorund/first"


import (

    "flag"


    "play.ground/foo"

)

會發生什么?首先執行包init(),first正確注冊tf標志,然后foo將嘗試再次執行該操作,失敗并報告錯誤。


示例輸出(在Go Playground上嘗試):


/tmpfs/play flag redefined: tf

panic: /tmpfs/play flag redefined: tf


goroutine 1 [running]:

flag.(*FlagSet).Var(0xc000062180, {0x4c3188, 0xc0000142a0}, {0x4a2642, 0x2}, {0x0, 0x0})

    /usr/local/go-faketime/src/flag/flag.go:980 +0x2f9

flag.StringVar(...)

    /usr/local/go-faketime/src/flag/flag.go:851

play.ground/foo.init.0()

    /tmp/sandbox1464715048/foo/foo.go:10 +0x7d

如您所見,foo.go第 10 行注冊了tf標志。任務完成。


筆記:


許多編輯器在保存時自動設置格式,這可能涉及重新排列/重新組合導入,因此您的play.ground/first導入可能會向下移動,而不是第一個。為避免這種情況,請勿使用自動格式化功能,或為此包選擇一個在自動格式化后將首先保留的名稱。


筆記2:


Spec: Package initialization聲明了初始化包的要求和規則,并沒有指定處理導入的順序(唯一保證的是所有引用的包在使用之前都會被遞歸初始化)。這意味著盡管當前的編譯器按照列出的方式處理它們,但您不能 100% 依賴它。還有一個問題,即使是main包也有多個源文件,以不同的順序向編譯器提供它們也可能會改變初始化順序。該規范將此作為“建議”:


為了確保可重現的初始化行為,鼓勵構建系統以詞法文件名順序向編譯器呈現屬于同一包的多個文件。


查看完整回答
反對 回復 2023-02-06
  • 1 回答
  • 0 關注
  • 155 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號