Golang 面試題解析 2
12.是否可以編譯通過?如果通過,輸出什麼?
type只能使用在interface https://play.golang.org/p/w4CmYC2HdSA
func main() {
i := GetValue()
switch i.(type) {
case int:
println("int")
case string:
println("string")
case interface{}:
println("interface")
default:
println("unknown")
}
}
func GetValue() int {
return 1
}
編譯失敗,因為type只能使用在interface
解法
https://play.golang.org/p/-F47FJ72ByD
var i interface{}= GetValue()
13.下面函式有什麼問題?
func funcMui(x,y int)(sum int,error){
return x+y,nil
}
在函式有多個返回值時,只要有一個返回值有指定命名,其他的也必須有命名。 如果返回值有有多個返回值必須加上括號; 如果只有一個返回值並且有命名也需要加上括號; 此處函式第一個返回值有sum名稱,第二個未命名,所以錯誤。
解法
func funcMui(x,y int)(sum int,err error){ return x+y,nil }
14.是否可以編譯通過?如果通過,輸出什麼?
https://play.golang.org/p/wxE5r5DQbs9
package main
func main() {
println(DeferFunc1(1))
println(DeferFunc2(1))
println(DeferFunc3(1))
}
func DeferFunc1(i int) (t int) {
t = i
defer func() {
t += 3
}()
return t
}
func DeferFunc2(i int) int {
t := i
defer func() {
t += 3
}()
return t
}
func DeferFunc3(i int) (t int) {
defer func() {
t += i
}()
return 2
}
// 4 1 3
需要明確一點是defer需要在函式結束前執行。 函式返回值名字會在函式起始處被初始化為對應型別的零值並且作用域為整個函式 DeferFunc1有函式返回值t作用域為整個函式,在return之前defer會被執行,所以t會被修改,返回4; DeferFunc2函式中t的作用域為函式,返回1; DeferFunc3返回3
15.是否可以編譯通過?如果通過,輸出什麼?
編譯不過 first argument to append must be slice; have *[]int
https://play.golang.org/p/8eShs3oaNOm
package main
import "fmt"
func main() {
list := new([]int)
list = append(list, 1)
fmt.Println(list)
}
// ./prog.go:6:15: first argument to append must be slice; have *[]int
解法1. list := *new([]int)
https://go.dev/play/p/wDNGV8mN5_5
package main
import "fmt"
func main() {
list := *new([]int)
list = append(list, 1)
fmt.Println(list)
}
解法2. list := make([]int, 0)
https://go.dev/play/p/c__RrDt3N_h
package main
import "fmt"
func main() {
list := make([]int, 0)
list = append(list, 1)
fmt.Println(list)
}
16.是否可以編譯通過?如果通過,輸出什麼? : append slice 時候要補上 '...'
編譯不過./prog.go:8:13: cannot use s2 (type []int) as type int in append
package main
import "fmt"
func main() {
s1 := []int{1, 2, 3}
s2 := []int{4, 5}
s1 = append(s1, s2)
fmt.Println(s1)
}
// ./prog.go:8:13: cannot use s2 (type []int) as type int in append
append slice時候要補上 '...' s1 = append(s1, s2...)
解法
https://go.dev/play/p/Gb9Tfc6JS7y
package main
import "fmt"
func main() {
s1 := []int{1, 2, 3}
s2 := []int{4, 5}
s1 = append(s1, s2...)
fmt.Println(s1)
}
17.是否可以編譯通過?如果通過,輸出什麼? map, slice 不能用==比較
但可以用reflect.DeepEqual進行比較
package main
import "fmt"
func main() {
sn1 := struct {
age int
name string
}{age: 11, name: "qq"}
sn2 := struct {
age int
name string
}{age: 11, name: "qq"}
if sn1 == sn2 {
fmt.Println("sn1 == sn2") // 會印
}
sm1 := struct {
age int
m map[string]string
}{age: 11, m: map[string]string{"a": "1"}}
sm2 := struct {
age int
m map[string]string
}{age: 11, m: map[string]string{"a": "1"}}
if sm1 == sm2 { // 不能比較
fmt.Println("sm1 == sm2")
}
}
// ./prog.go:28:9: invalid operation: sm1 == sm2 (struct containing map[string]string cannot be compared)
// https://play.golang.org/p/MFtW4ymOZFn
編譯不通過: invalid operation: sm1 == sm2
進行結構體比較時候,只有相同型別的結構體才可以比較, 結構體是否相同不但與屬性型別個數有關,還與屬性順序相關。 https://go.dev/play/p/IrUccxWD_h0
sn3:= struct {
name string
age int
}{age:11,name:"qq"}
if sn1 == sn3 { // 不能比較
fmt.Println("sn1 == sn3")
}
sn3與sn1就不是相同的結構體了,不能比較。 還有一點需要注意的是結構體是相同的,但是結構體屬性中有不可以比較的型別,如 map,slice。 如果該結構屬性都是可以比較的,那麼就可以使用"=="進行比較操作。
解法
可以使用reflect.DeepEqual進行比較 https://go.dev/play/p/siCKMIkvW0l
package main
import (
"fmt"
"reflect"
)
func main() {
sm1 := struct {
age int
m map[string]string
}{age: 11, m: map[string]string{"a": "1"}}
sm2 := struct {
age int
m map[string]string
}{age: 11, m: map[string]string{"a": "1"}}
if reflect.DeepEqual(sm1, sm2) {
fmt.Println("sm1 == sm2")
}
}
18.是否可以編譯通過?如果通過,輸出什麼? Interface 包含了兩個指針 1. 類型的指針 2. 實際的值的指針
https://play.golang.org/p/HCTKvqNGN7E
func Foo(x interface{}) {
if x == nil {
fmt.Println("empty interface")
return
}
fmt.Println("non-empty interface") // 輸出這個
}
func main() {
var x *int = nil
Foo(x)
}
// non-empty interface
- Interface 包含了兩個指針: 1. 類型的指針 2. 實際的值的指針
- https://studygolang.com/articles/10635
19.是否可以編譯通過?如果通過,輸出什麼? nil 可以用作 interface、function、pointer、map、slice 和 channel
package main
import "fmt"
func GetValue(m map[int]string, id int) (string, bool) {
if _, exist := m[id]; exist {
return "存在資料", true
}
return nil, false // 出錯 cannot use nil as type string in return argument
}
func main() {
intmap := map[int]string{
1: "a",
2: "bb",
3: "ccc",
}
v, err := GetValue(intmap, 3)
fmt.Println(v, err)
}
// ./prog.go:9:2: cannot use nil as type string in return argument
nil 可以用作 interface、function、pointer、map、slice 和 channel 的"空值"。但是如果不特別指定的話,Go 語言不能識別型別,所以會報錯。報:
cannot use nil as type string in return argument.
20.是否可以編譯通過?如果通過,輸出什麼?
https://play.golang.org/p/XwtR_I0fQdp
package main
import "fmt"
const (
x = iota
y
z = "zz"
k
p = iota
)
func main() {
fmt.Println(x,y,z,k,p)
}
// 0 1 zz zz 4
iota是golang語言的常量計數器,只能在常量的表達式中使用, 每次const 出現時,都會讓iota 初始化為0.
https://go.dev/play/p/fE3BsjhaLpL
package main
import "fmt"
const (
Apple, Banana = iota + 1, iota + 2 // 0: 0+1, 0+2
Cherimoya, Durian // 1: 1+1, 1+2
Elderberry, Fig // 2: 2+1, 2+2
)
func main() {
fmt.Println(Apple) // 0+1 = 1
fmt.Println(Banana) // 0+2 = 2
fmt.Println(Cherimoya) // 1+1 = 2
fmt.Println(Durian) // 1+2 = 3
fmt.Println(Elderberry) // 2+1 = 3
fmt.Println(Fig) // 2+2 = 4
}
// iota 在下一行增長,而不是立即取得它的引用。
// Apple: 1
// Banana: 2
// Cherimoya: 2
// Durian: 3
// Elderberry: 3
// Fig: 4
<!-- ## Install {#install}
The first thing is to get the GitBook API client.
</div>$ npm install gitbook-api
$ go get github.com/GitbookIO/go-gitbook-api