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有什麼區別?

  1. 使用場景不同

    • for 可以
    • 遍歷array和slice
    • 遍歷key為整型遞增的map
    • 遍歷string
  2. for range

    • for range可以完成所有for可以做的事情,卻能做到for不能做的,包括
    • 遍歷key為string類型的map並同時獲得key和value
    • 遍歷channel
  3. 實現不同
    • 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]int https://go.dev/play/p/SGOMERYIMNb


Reference

© Kimi Tsai all right reserved.            Updated : 2023-07-12 09:04:53

results matching ""

    No results matching ""

    results matching ""

      No results matching ""