<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                1、寫出下面代碼輸出內容。 ~~~ package main import ( "fmt" ) func main() { defer_call() } func defer_call() { defer func() { fmt.Println("打印前") }() defer func() { fmt.Println("打印中") }() defer func() { fmt.Println("打印后") }() panic("觸發異常") } ~~~ 答: 輸出內容為: ~~~ 打印后 打印中 打印前 panic: 觸發異常 ~~~ 解析: 考察對defer的理解,defer函數屬延遲執行,延遲到調用者函數執行 return 命令前被執行。多個defer之間按LIFO先進后出順序執行。 故考題中,在Panic觸發時結束函數運行,在return前先依次打印:打印后、打印中、打印前 。最后由runtime運行時拋出打印panic異常信息。 需要注意的是,函數的return value 不是原子操作.而是在編譯器中分解為兩部分:返回值賦值 和 return 。而defer剛好被插入到末尾的return前執行。故可以在derfer函數中修改返回值。如下示例: ~~~ package main import ( "fmt" ) func main() { fmt.Println(doubleScore(0)) //0 fmt.Println(doubleScore(20.0)) //40 fmt.Println(doubleScore(50.0)) //50 } func doubleScore(source float32) (score float32) { defer func() { if score < 1 || score >= 100 { //將影響返回值 score = source } }() score = source * 2 return //或者 //return source * 2 } ~~~ 運行結果: ~~~ 0 40 50 ~~~ 該實例可以在defer中修改返回值score的值。 2、以下代碼有什么問題,說明原因 ~~~ package main import ( "fmt" ) type student struct { Name string Age int } func pase_student() map[string]*student { m := make(map[string]*student) stus := []student{ {Name: "zhou", Age: 24}, {Name: "li", Age: 23}, {Name: "wang", Age: 22}, } for _, stu := range stus { m[stu.Name] = &stu } return m } func main() { students := pase_student() for k, v := range students { fmt.Printf("key=%s,value=%v \n", k, v) } } ~~~ 運行結果: ~~~ key=zhou,value=&{wang 22} key=li,value=&{wang 22} key=wang,value=&{wang 22} ~~~ 答: 輸出的均是相同的值:&{wang 22} 解析: 因為for遍歷時,變量stu指針不變,每次遍歷僅進行struct值拷貝,故m[stu.Name]=&stu實際上一致指向同一個指針,最終該指針的值為遍歷的最后一個struct的值拷貝。形同如下代碼: ~~~ var stu student for _, stu = range stus { m[stu.Name] = &stu } ~~~ 修正方案,取數組中原始值的指針: ~~~ for i, _ := range stus { stu := stus[i] m[stu.Name] = &stu } ~~~ 3、下面的代碼會輸出什么,并說明原因 ~~~ package main import ( "fmt" "runtime" "sync" ) func main() { runtime.GOMAXPROCS(1) wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < 10; i++ { go func() { fmt.Println("i: ", i) wg.Done() }() } for i := 0; i < 10; i++ { go func(i int) { fmt.Println("i: ", i) wg.Done() }(i) } wg.Wait() } ~~~ 運行結果: ~~~ i: 9 i: 10 i: 10 i: 10 i: 10 i: 10 i: 10 i: 10 i: 10 i: 10 i: 10 i: 0 i: 1 i: 2 i: 3 i: 4 i: 5 i: 6 i: 7 i: 8 ~~~ 答: 將隨機輸出數字,但前面一個循環中并不會輸出所有值。 解析: 實際上第一行是否設置CPU為1都不會影響后續代碼。 2017年7月25日:將GOMAXPROCS設置為1,將影響goroutine的并發,后續代碼中的go func()相當于串行執行。 兩個for循環內部go func 調用參數i的方式是不同的,導致結果完全不同。這也是新手容易遇到的坑。 第一個go func中i是外部for的一個變量,地址不變化。遍歷完成后,最終i=10。故go func執行時,i的值始終是10(10次遍歷很快完成)。 第二個go func中i是函數參數,與外部for中的i完全是兩個變量。尾部(i)將發生值拷貝,go func內部指向值拷貝地址。 4、下面代碼會輸出什么? ~~~ package main import ( "fmt" ) type People struct{} func (p *People) ShowA() { fmt.Println("showA") p.ShowB() } func (p *People) ShowB() { fmt.Println("showB") } type Teacher struct { People } func (t *Teacher) ShowB() { fmt.Println("teacher showB") } func main() { t := Teacher{} t.ShowA() } ~~~ 答: 運行結果: ~~~ showA showB ~~~ 解析: Go中沒有繼承! 沒有繼承!沒有繼承!是叫組合!組合!組合! 這里People是匿名組合People。被組合的類型People所包含的方法雖然升級成了外部類型Teacher這個組合類型的方法,但他們的方法(ShowA())調用時接受者并沒有發生變化。 這里仍然是People。畢竟這個People類型并不知道自己會被什么類型組合,當然也就無法調用方法時去使用未知的組合者Teacher類型的功能。 因此這里執行t.ShowA()時,在執行ShowB()時該函數的接受者是People,而非Teacher。 5、下面代碼會觸發異常嗎?請詳細說明 ~~~ package main import ( "fmt" "runtime" ) func main() { runtime.GOMAXPROCS(1) int_chan := make(chan int, 1) string_chan := make(chan string, 1) int_chan <- 1 string_chan <- "hello" select { case value := <-int_chan: fmt.Println(value) case value := <-string_chan: panic(value) } } ~~~ 在線運行 答: 有可能觸發異常,是隨機事件。 解析 單個chan如果無緩沖時,將會阻塞。但結合 select可以在多個chan間等待執行。有三點原則: select 中只要有一個case能return,則立刻執行。 當如果同一時間有多個case均能return則偽隨機方式抽取任意一個執行。 如果沒有一個case能return則可以執行”default”塊。 此考題中的兩個case中的兩個chan均能return,則會隨機執行某個case塊。故在執行程序時,有可能執行第二個case,觸發異常。 6、下面代碼輸出什么? ~~~ package main import ( "fmt" ) func calc(index string, a, b int) int { ret := a + b fmt.Println(index, a, b, ret) return ret } func main() { a := 1 //line 1 b := 2 //2 defer calc("1", a, calc("10", a, b)) //3 a = 0 //4 defer calc("2", a, calc("20", a, b)) //5 b = 1 //6 } ~~~ 答: 運行結果: ~~~ 10 1 2 3 20 0 2 2 2 0 2 2 1 1 3 4 ~~~ 解析: 在解題前需要明確兩個概念: defer是在函數末尾的return前執行,先進后執行,具體見問題1。 函數調用時 int 參數發生值拷貝。 不管代碼順序如何,defer calc func中參數b必須先計算,故會在運行到第三行時,執行calc("10",a,b)輸出:10 1 2 3得到值3,將cal("1",1,3)存放到延后執執行函數隊列中。 執行到第五行時,現行計算calc("20", a, b)即calc("20", 0, 2)輸出:20 0 2 2得到值2,將cal("2",0,2)存放到延后執行函數隊列中。 執行到末尾行,按隊列先進后出原則依次執行:cal("2",0,2)、cal("1",1,3) ,依次輸出:2 0 2 2、1 1 3 4 。 7、請寫出以下輸入內容 ~~~ package main import ( "fmt" ) func main() { s := make([]int, 5) s = append(s, 1, 2, 3) fmt.Println(s) } ~~~ 答: 運行結果: ~~~ [0 0 0 0 0 1 2 3] ~~~ 解析: make可用于初始化數組,第二個可選參數表示數組的長度。數組是不可變的。 當執行make([]int,5)時返回的是一個含義默認值(int的默認值為0)的數組:[0,0,0,0,0]。而append函數是便是在一個數組或slice后面追加新的元素,并返回一個新的數組或slice。 這里append(s,1,2,3)是在數組s的繼承上追加三個新元素:1、2、3,故返回的新數組為[0 0 0 0 0 1 2 3] 8、下面的代碼有什么問題? ~~~ package main import ( "fmt" "sync" ) type UserAges struct { ages map[string]int sync.Mutex } func (ua *UserAges) Add(name string, age int) { ua.Lock() defer ua.Unlock() ua.ages[name] = age } func (ua *UserAges) Get(name string) int { if age, ok := ua.ages[name]; ok { return age } return -1 } func main() { userAges := &UserAges{ ages: make(map[string]int), } for i := 0; i < 10000; i++ { go userAges.Add("oldboy", i) go func() { age := userAges.Get("oldboy") fmt.Println(age) }() } } ~~~ 答: 在執行 Get方法時可能被panic 解析: 雖然有使用sync.Mutex做寫鎖,但是map是并發讀寫不安全的。map屬于引用類型,并發讀寫時多個協程見是通過指針訪問同一個地址,即訪問共享變量,此時同時讀寫資源存在競爭關系。會報錯誤信息:“fatal error: concurrent map read and map write”。 可以在在線運行中執行,復現該問題。那么如何改善呢? 當然Go1.9新版本中將提供并發安全的map。首先需要了解兩種鎖的不同: sync.Mutex互斥鎖 sync.RWMutex讀寫鎖,基于互斥鎖的實現,可以加多個讀鎖或者一個寫鎖。 利用讀寫鎖可實現對map的安全訪問,在線運行改進版 。利用RWutex進行讀鎖。 ~~~ type RWMutex func (rw *RWMutex) Lock() func (rw *RWMutex) RLock() func (rw *RWMutex) RLocker() Locker func (rw *RWMutex) RUnlock() func (rw *RWMutex) Unlock() ~~~ 正確代碼: ~~~ package main import ( "fmt" "sync" ) type UserAges struct { ages map[string]int sync.RWMutex } func (ua *UserAges) Add(name string, age int) { ua.Lock() defer ua.Unlock() ua.ages[name] = age } func (ua *UserAges) Get(name string) int { ua.Lock() defer ua.Unlock() if age, ok := ua.ages[name]; ok { return age } return -1 } func main() { userAges := &UserAges{ ages: make(map[string]int), } for i := 0; i < 10000; i++ { go userAges.Add("oldboy", i) go func() { age := userAges.Get("oldboy") fmt.Println(age) }() } } ~~~ 9、下面的迭代會有什么問題? ~~~ func (set *threadSafeSet) Iter() <-chan interface{} { ch := make(chan interface{}) go func() { set.RLock() for elem := range set.s { ch <- elem } close(ch) set.RUnlock() }() return ch } ~~~ 答: 內部迭代出現阻塞。默認初始化時無緩沖區,需要等待接收者讀取后才能繼續寫入。 解析: chan在使用make初始化時可附帶一個可選參數來設置緩沖區。默認無緩沖,題目中便初始化的是無緩沖區的chan,這樣只有寫入的元素直到被讀取后才能繼續寫入,不然就一直阻塞。 設置緩沖區大小后,寫入數據時可連續寫入到緩沖區中,直到緩沖區被占滿。從chan中接收一次便可從緩沖區中釋放一次。可以理解為chan是可以設置吞吐量的處理池。 ch := make(chan interface{}) 和 ch := make(chan interface{},1)是不一樣的 無緩沖的 不僅僅是只能向 ch 通道放 一個值 而是一直要有人接收,那么ch <- elem才會繼續下去,要不然就一直阻塞著,也就是說有接收者才去放,沒有接收者就阻塞。 而緩沖為1則即使沒有接收者也不會阻塞,因為緩沖大小是1只有當 放第二個值的時候 第一個還沒被人拿走,這時候才會阻塞。 10、以下代碼能編譯過去嗎?為什么? ~~~ package main import ( "fmt" ) type People interface { Speak(string) string } type Stduent struct{} func (stu *Stduent) Speak(think string) (talk string) { if think == "bitch" { talk = "You are a good boy" } else { talk = "hi" } return } func main() { var peo People = Stduent{} think := "bitch" fmt.Println(peo.Speak(think)) } ~~~ 答: 編譯失敗,值類型 Student{} 未實現接口People的方法,不能定義為 People類型。 解析: 考題中的 func (stu *Stduent) Speak(think string) (talk string) 是表示結構類型*Student的指針有提供該方法,但該方法并不屬于結構類型Student的方法。因為struct是值類型。 修改方法: 定義為指針: ~~~ var peo People = &Stduent{} ~~~ 方法定義在值類型上,指針類型本身是包含值類型的方法。 ~~~ func (stu Stduent) Speak(think string) (talk string) { //... } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看