Golang面試題解析 5
41.執行下面的代碼發生什麼? map需要初始化後才能使用
map需要初始化後才能使用 https://go.dev/play/p/GmVoRZYs0GO
package main
import "fmt"
type Param map[string]interface{}
type Show struct{ *Param }
func main() {
s := new(Show)
s.Param["NTD"] = 10000 // 這裡出錯
fmt.Println(s)
}
/*
./prog.go:10:9: invalid operation: s.Param["NTD"] (type *Param does not support indexing)
*/
解法
map需要初始化後才能使用
https://go.dev/play/p/GlF8S9ZwaPr
package main
import "fmt"
type Param map[string]interface{}
type Show struct{ Param }
type ShowP struct{ *Param }
func main() {
s := new(Show)
s.Param = make(map[string]interface{})
s.Param["NTD"] = 100
fmt.Println(s.Param)
sp := new(ShowP)
var list Param = Param{"NTD":500,}
sp.Param = &list
fmt.Println(*sp.Param)
}
42.編譯執行下面代碼會出現什麼?
https://go.dev/play/p/PjwC6sF75S6
package main
import "fmt"
type student struct{ Name string }
func foo(v interface{}) {
switch msg := v.(type) {
case *student, student:
msg.Name = "qq" // 這裡出錯
fmt.Print(msg)
}
}
func main() {
foo(student{})
}
/*
./prog.go:10:6: msg.Name undefined (type interface {} is interface with no methods)
*/
解法
msg不屬於student類型,所以沒有Name欄位。msg屬於interface{}
https://go.dev/play/p/4XZlpNx4JIP
package main
import "fmt"
type student struct{ Name string }
func foo(v interface{}) {
switch v.(type) {
case *student, student:
msg := v.(student)
msg.Name = "qq"
fmt.Print(msg)
}
}
func main() {
foo(student{})
}
43.執行下面代碼會出現什麼?
因為name的首字母是小寫, 導致其他包無法訪問,所以輸出空結構
https://go.dev/play/p/1soegZIzOMj
package main
import (
"encoding/json"
"fmt"
)
type People struct {
name string `json:"name"`
}
func main() {
js := `{ "name":"11" }`
var p People
err := json.Unmarshal([]byte(js), &p)
if err != nil {
fmt.Println("err: ", err)
return
}
fmt.Println("people: ", p)
}
/*
people: {}
*/
解法
name 改成大寫 Name
https://go.dev/play/p/rwGLjMRN_Dz
type People struct {
Name string `json:"name"`
}
44.以下代碼有什麼問題? 有方向的channel不可被關閉
package main
func Stop( stop <-chan bool) {
close(stop)
}
有方向的channel不可被關閉
45.實現一個函數可以根據指定的 size 切割切片為多個小切片
https://go.dev/play/p/FaegMavypfE
package main
import (
"fmt"
"math"
)
func main() {
// 容量11的slice, 每5個長度切成一個
lenth := 11
size := 5
list := make([]int, 0, lenth)
for i := 0; i < lenth; i++ {
list = append(list, i)
}
// fmt.Println("list = ", list) //[0 1 2 3 4 5 6 7 8 9 10]
spliltList := SpiltList(list, size)
for i, sp := range spliltList {
fmt.Printf("第%d組 ==> %v \n", i, sp)
}
}
func SpiltList(list []int, size int) [][]int {
lens := len(list)
mod := math.Ceil(float64(lens) / float64(size))
spliltList := make([][]int, 0)
for i := 0; i < int(mod); i++ {
tmpList := make([]int, 0, size)
// fmt.Println("i=", i)
if i == int(mod)-1 {
// 最後一組
tmpList = list[i*size:]
} else {
tmpList = list[i*size : i*size+size]
}
spliltList = append(spliltList, tmpList)
}
return spliltList
}
/*
第0組 ==> [0 1 2 3 4]
第1組 ==> [5 6 7 8 9]
第2組 ==> [10]
*/
[!]46.實現兩個go輪流輸出:A1B2C3.....Z26
有被考過 https://play.golang.org/p/ubZjentme9Y
方法一: 緩衝
https://go.dev/play/p/iJ-gYxeqv31
func ChannelFunc() {
abc := make(chan int, 1)
num := make(chan int, 1)
abc <- 0
// 取得字母 A~Z
go func() {
for i := 65; i <= 90; i++ {
<-abc //等待abc
fmt.Printf("%v", string(rune(i))) // 印字母
num <- i // 讓num channel 有東西, 才可以跑下面的go fun
}
return
}()
// 取得數字 1~26
go func() {
for i := 1; i <= 26; i++ {
<-num //等待num
fmt.Printf("%v", i) // 印數字
abc <- i
}
return
}()
time.Sleep(1 * time.Second)
fmt.Println()
}
方法二: 無緩衝
https://go.dev/play/p/T2HUkBIW1kg
func Channel1Func() {
abc := make(chan int)
num := make(chan int)
// abc
go func() {
for i := 65; i <= 90; i++ {
fmt.Printf("%v", string(rune(i)))
abc <- i
<-num //等 num 處理好
}
return
}()
go func() {
for i := 1; i <= 26; i++ {
<-abc // 等 abc 處理好
fmt.Printf("%v", i)
num <- i
}
return
}()
time.Sleep(1 * time.Second)
fmt.Println()
}
方法三: mutex
https://go.dev/play/p/F830P2F_BiU
func ChannelLock() {
abcMux := sync.Mutex{}
numMux := sync.Mutex{}
// 數字鎖
numMux.Lock()
go func() {
for i := 65; i <= 90; i++ {
// 字母鎖
abcMux.Lock()
fmt.Printf("%v", string(rune(i)))
// 數字解鎖
numMux.Unlock()
}
return
}()
go func() {
for i := 1; i <= 26; i++ {
// 數字鎖
numMux.Lock()
fmt.Printf("%v", i)
// 字母解鎖
abcMux.Unlock()
}
return
}()
time.Sleep(1 * time.Second)
fmt.Println()
}
47.執行下面代碼輸出什麼?
https://play.golang.org/p/0Lcl62ZQG0j
package main
import "fmt"
func main() {
five := []string{"Annie", "Betty", "Charley", "Doug", "Edward"}
for _, v := range five {
five = five[:2]
// fmt.Println("five:", five)
fmt.Printf("v[%s]\n", v) // v[Annie] v[Betty] v[Charley] v[Doug] v[Edward]
}
fmt.Println("five:", five) // [Annie Betty]
}
/*
v[Annie]
v[Betty]
v[Charley]
v[Doug]
v[Edward]
five: [Annie Betty]
*/
range副本機制, 循環內的切片值會縮減為2,但循環將在切片值的自身副本上進行操作。 這允許循環使用原始長度進行疊代而沒有任何問題,因為後備數組仍然是完整的。
for i := 0; i < len(five); i++ {
five = five[:2]
fmt.Printf("v[%s]\n", five[i])
}
/*
v[Annie]
v[Betty]
*/
48.for 和 for range有什麼區別?
使用場景不同
for可以- 遍歷array和slice
- 遍歷key為整型遞增的map
- 遍歷string
for range- for range可以完成所有for可以做的事情,卻能做到for不能做的,包括
- 遍歷key為string類型的map並同時獲得key和value
- 遍歷channel
- 實現不同
for可以獲取到的是被循環對性的元素本身,可以對其進行修改for range使用值拷貝的方式代替被遍歷的元素本身,是一個值拷貝,而不是元素本身。
49.解決下面問題:輸出 MutilParam= [ssss [1 2 3 4]]如何做到輸出為[ssss 1 2 3 4]?
https://go.dev/play/p/h7wVWBLq7-R
package main
import "fmt"
func MutilParam(p ...interface{}) {
fmt.Println("MutilParam=", p)
}
func main() {
MutilParam("ssss", 1, 2, 3, 4) //[ssss 1 2 3 4]
iis := []int{1, 2, 3, 4}
MutilParam("ssss", iis) //輸出MutilParam= [ssss [1 2 3 4]]如何做到輸出為[ssss 1 2 3 4]
}
解法一
https://go.dev/play/p/Jx43LWMaRzv
func main() {
iis := []int{1, 2, 3, 4}
tmpParams := make([]interface{}, 0, len(iis)+1)
tmpParams = append(tmpParams, "ssss")
for _, ii := range iis {
tmpParams = append(tmpParams, ii)
}
MutilParam(tmpParams...)
}
解法二 反射
https://go.dev/play/p/9NIvHxEyhWh
func main() {
iis := []int{1, 2, 3, 4}
f := MutilParam
value := reflect.ValueOf(f)
pps := make([]reflect.Value, 0, len(iis)+1)
pps = append(pps, reflect.ValueOf("ssss"))
for _, ii := range iis {
pps = append(pps, reflect.ValueOf(ii))
}
value.Call(pps)
}
50.編譯並運行如下代碼會發生什麼?
https://go.dev/play/p/AL_tOH99GY6
package main
import "fmt"
func main() {
mmap := make(map[map[string]string]int, 0) // ./prog.go:6:15: invalid map key type map[string]string
mmap[map[string]string{"a": "a"}] = 1
mmap[map[string]string{"b": "b"}] = 1
mmap[map[string]string{"c": "c"}] = 1
fmt.Println(mmap)
}
/*
./test.go:6:15: invalid map key type map[string]string
*/
golang中的map的 key 可以是很多種類型,比如 bool, 數字,string, 指針, channel , 還有只包含前面幾個類型的 interface types, structs, arrays 但key不可以是
slice,map,function, 因為這幾個沒法用 == 來判斷,是不可比較類型。 可以將map[map[string]string]int改為map[*struct]inthttps://go.dev/play/p/SGOMERYIMNb