Golang 面試題解析 3
21.編譯執行下面代碼會出現什麼?
:= 定義變數時同時出數話,不能提供數據類型,只能在函數內部使用
https://go.dev/play/p/P5031XtJj7P
package main
var(
size :=1024 // 這邊會出錯
max_size = size*2
)
func main() {
println(size,max_size)
}
// prog.go:3:10: expected ';', found ':=' (and 1 more errors)
變量簡短模式限制: - 定義變量同時顯式初始化 - 不能提供數據類型 - 只能在函數內部使用
22.下面函數有什麼問題? const通常會被編譯器在預處理階段直接展開,作為指令數據使用
https://go.dev/play/p/5IbC47pIVaH
package main
const cl = 100
var bl = 123
func main() {
println(&bl, bl)
println(&cl, cl) // &cl 這邊會出錯
}
// ./prog.go:9:10: cannot take the address of cl
./prog.go:9:10: cannot take the address of cl, 常數不同於變量的在運行期分配內存,常數通常會被編譯器在預處理階段直接展開,作為指令數據使用,
23.編譯執行下面代碼會出現什麼? goto不能跳轉到其他函數或者內層代碼
https://go.dev/play/p/7vEcjr2mibC
package main
func main() {
for i := 0; i < 10; i++ {
loop:
println(i)
}
goto loop
}
./prog.go:9:7: goto loop jumps into block starting at ./prog.go:5:26
goto不能跳轉到其他函數或者內層代碼
24.編譯執行下面代碼會出現什麼?
https://go.dev/play/p/w2feiGVuG_x
package main
import "fmt"
func main() {
type MyInt1 int // defintion(定義MyInt1 為一個Int型態)
type MyInt2 = int // alias(別名, 將int 稱為 MyInt)
var i int = 9
var i1 MyInt1 = i // 這邊會出錯, 不能把一個int的值給 MyInt1這個型態
var i2 MyInt2 = i
fmt.Println(i1, i2)
}
./prog.go:9:6: cannot use i (type int) as type MyInt1 in assignment
Go 1.9 新特性 Type Alias 基於一個類型創建一個新類型,稱之為defintion;基於一個類型創建一個別名,稱之為alias。 MyInt1為稱之為defintion,雖然底層類型為int類型,但是不能直接賦值,需要強轉; MyInt2稱之為alias,可以直接賦值。i2 = 9
25.編譯執行下面代碼會出現什麼?
https://go.dev/play/p/uMm2CKBiehu
package main
import "fmt"
type User struct {
}
type MyUser1 User
type MyUser2 = User
func (i MyUser1) m1() {
fmt.Println("MyUser1.m1")
}
func (i User) m2() {
fmt.Println("User.m2")
}
func main() {
var i1 MyUser1
var i2 MyUser2
i1.m1() // MyUser1.m1
i2.m2() // User.m2
}
/*
MyUser1.m1
User.m2
*/
因為MyUser2完全等價於User,所以具有其所有的方法,並且其中一個新增了方法,另外一個也會有。但是i1.m2() 是不能執行的,因為MyUser1沒有定義該方法
26.編譯執行下面代碼會出現什麼?
https://go.dev/play/p/Ae_aNvhwRX6
package main
import "fmt"
type T1 struct {
}
func (t T1) m1() {
fmt.Println("T1.m1")
}
type T2 = T1
type MyStruct struct {
T1
T2
}
func main() {
my := MyStruct{}
my.m1() // 這邊會出錯, 會不知道是誰的m1() function
}
// ./prog.go:20:4: ambiguous selector my.m1
結果不限於方法,字段也也一樣;也不限於type alias,type defintion也是一樣的,只要有重複的方法、字段,就會有這種提示,因為不知道該選擇哪個。
解法
https://go.dev/play/p/R_C0E136fN8
my.T1.m1()
my.T2.m1()
27.編譯執行下面代碼會出現什麼?
https://play.golang.org/p/LG-EcwE5yqL
package main
import (
"errors"
"fmt"
)
var ErrDidNotWork = errors.New("did not work")
func DoTheThing(reallyDoIt bool) (err error) {
if reallyDoIt {
result, err := tryTheThing()
if err != nil || result != "it worked" {
err = ErrDidNotWork
}
}
return err
}
func tryTheThing() (string, error) {
return "", ErrDidNotWork
}
func main() {
fmt.Println(DoTheThing(true))
fmt.Println(DoTheThing(false))
}
/*
<nil>
<nil>
*/
因為 if 語句塊內的 err 變量會遮罩函數作用域內的 err 變量
解法
https://play.golang.org/p/Ir-rIeK7r3V
func DoTheThing(reallyDoIt bool) (err error) {
var result string
if reallyDoIt {
result, err = tryTheThing()
if err != nil || result != "it worked" {
err = ErrDidNotWork
}
}
return err
}
28.編譯執行下面代碼會出現什麼?
https://go.dev/play/p/sJfSHHrjdw3
package main
func test() []func() {
var funs []func()
for i:=0;i<2 ;i++ {
funs = append(funs, func() {
println(&i,i)
})
}
return funs
}
func main(){
funs:=test()
for _,f:=range funs{
f()
}
}
/*
0xc00002c008 2
0xc00002c008 2
*/
考點:閉包延遲求值 for循環復用局部變量i,每一次放入匿名函數的應用都是想一個變量。
解法
https://go.dev/play/p/5R1KtBjKyZX
func test2() []func() {
var funs []func()
for i:=0;i<2 ;i++ {
x:=i
funs = append(funs, func() {
println(&x,x)
})
}
return funs
}
/*
0xc000096000 0
0xc000096008 1
*/
29.編譯執行下面代碼會出現什麼? 閉包引用相同變數
閉包引用相同變數 https://go.dev/play/p/NtAXXtNWgXo
package main
func test(x int) (func(),func()) {
return func() {
println(x)
x+=10
}, func() {
println(x)
}
}
func main() {
a,b:=test(100)
a() // 100
b() // 110
}
/*
100
110
*/
閉包引用相同變數
30.編譯執行下面代碼會出現什麼?
panic 只有最後一個可以被 recover 捕獲,
panic("panic") -> defer的panic("defer panic") 是最後一個 panic
package main
import (
"fmt"
)
func main() {
defer func() {
if err:=recover();err!=nil{ // 收到2的panic
fmt.Println(err)
}else {
fmt.Println("fatal")
}
}()
defer func() {
panic("defer panic") // 2 觸發
}()
panic("panic") // 1 觸發
}
// defer panic
考點:panic僅有最後一個可以被revover捕獲 觸發panic("panic")後順序執行defer,但是defer中還有一個panic,所以覆蓋了之前的panic("panic")