1. 程式人生 > >Golang面試題解析(五)

Golang面試題解析(五)

import == all 允許 沒有 ron lang 不兼容 i++

41.執行下面的代碼發生什麽?
package main

type Param map[string]interface{}

type Show struct {
    *Param
}

func main() {
    s := new(Show)
    s.Param["RMB"] = 10000
}

考點:map初始化

map需要初始化後才能使用。
編譯錯誤:invalid operation: s.Param["RMB"] (type *Param does not support indexing)

42.執行下面的代碼發生什麽?

package main
import "fmt"

type student struct {
    Name string
}

func zhoujielun(v interface{}) {
    switch msg := v.(type) {
    case *student, student:
        msg.Name = "qq"
        fmt.Print(msg)
    }
}

考點:類型轉換

msg不屬於student類型,所以沒有Name字段。
改為:

s := v.(student)
s.Name = "qq"

43.執行下面的代碼發生什麽?

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)
}

考點:結構體訪問控制

這道題坑很大,很多同學一看就以為是p的初始化問題,實際上是因為name首字母是小寫,導致其他包不能訪問,所以輸出為空結構體。
改為:

type People struct {
    Name string `json:"name"`
}

44.以下代碼有什麽問題?

package main

func Stop(stop <-chan bool) {
    close(stop)
}

考點:close channel

有方向的channel不可被關閉

45.實現一個函數可以根據指定的size切割切片為多個小切片

解析

func main() {
    lenth := 11
    size := 5
    list := make([]int, 0, lenth)
    for i := 0; i < lenth; i++ {
        list = append(list, i)
    }
    SpiltList(list, size)
}

func SpiltList(list []int, size 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)
    }
    for i, sp := range spliltList {
        fmt.Println(i, " ==> ", sp)
    }
}

46.實現兩個go輪流輸出:A1B2C3.....Z26

解析

方法一:有緩沖chan

func ChannelFunc() {
    zimu := make(chan int, 1)
    suzi := make(chan int, 1)
    zimu <- 0
    // zimu
    go func() {
        for i := 65; i <= 90; i++ {
            <-zimu
            fmt.Printf("%v", string(rune(i)))
            suzi <- i
        }
        return
    }()

    go func() {
        for i := 1; i <= 26; i++ {
            <-suzi
            fmt.Printf("%v", i)
            zimu <- i
        }
        return
    }()

    time.Sleep(1 * time.Second)
    fmt.Println()
}

方法二:無緩沖chan

func Channel1Func() {
    zimu := make(chan int)
    suzi := make(chan int)

    // zimu
    go func() {
        for i := 65; i <= 90; i++ {
            fmt.Printf("%v", string(rune(i)))
            zimu <- i
            <-suzi
        }
        return
    }()

    go func() {
        for i := 1; i <= 26; i++ {
            <-zimu
            fmt.Printf("%v", i)
            suzi <- i
        }
        return
    }()

    time.Sleep(10 * time.Second)
    fmt.Println()
}

方法三:使用鎖

大家可以自己實現,把結果留言給我,答案後續公布。

47.執行下面代碼輸出什麽?

package main

// 47.執行下面代碼輸出什麽?
import "fmt"

func main() {
    five := []string{"Annie", "Betty", "Charley", "Doug", "Edward"}

    for _, v := range five {
        five = five[:2]
        fmt.Printf("v[%s]\n", v)
    }
}

考點:range副本機制

循環內的切片值會縮減為2,但循環將在切片值的自身副本上進行操作。 這允許循環使用原始長度進行叠代而沒有任何問題,因為後備數組仍然是完整的。
結果:

v[Annie]
v[Betty]
v[Charley]
v[Doug]
v[Edward]

48.for 和 for range有什麽區別?

考點:for range

  1. 使用場景不同
    for可以
    • 遍歷array和slice
    • 遍歷key為整型遞增的map
    • 遍歷string
      for range可以完成所有for可以做的事情,卻能做到for不能做的,包括
    • 遍歷key為string類型的map並同時獲取key和value
    • 遍歷channel
  2. 實現不同
    for可以獲取到的是被循環對象的元素本身,可以對其進行修改;
    for range使用值拷貝的方式代替被遍歷的元素本身,是一個值拷貝,而不是元素本身。

49.解決下面問題:輸出MutilParam= [ssss [1 2 3 4]]如何做到輸出為[ssss 1 2 3 4]?

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]
}

考點:函數變參

這樣的情況會在開源類庫如xorm升級版本後出現Exce函數不兼容的問題。
解決方式有兩個:

方法一:interface[]

tmpParams := make([]interface{}, 0, len(iis)+1)
tmpParams = append(tmpParams, "ssss")
for _, ii := range iis {
    tmpParams = append(tmpParams, ii)
}
MutilParam(tmpParams...)

方法二:反射

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.編譯並運行如下代碼會發生什麽?

package main

// 50.編譯並運行如下代碼會發生什麽?
import "fmt"

func main() {
    mmap := make(map[map[string]string]int, 0)
    mmap[map[string]string{"a": "a"}] = 1
    mmap[map[string]string{"b": "b"}] = 1
    mmap[map[string]string{"c": "c"}] = 1
    fmt.Println(mmap)
}

考點:map key類型

golang中的map,的 key 可以是很多種類型,比如 bool, 數字,string, 指針, channel , 還有 只包含前面幾個類型的 interface types, structs, arrays。
顯然,slice, map 還有 function 是不可以了,因為這幾個沒法用 == 來判斷,即不可比較類型。
可以將map[map[string]string]int改為map[struct]int

Golang面試題解析(五)