<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go 語言筆試面試題(基礎(chǔ)語法)

          共 4349字,需瀏覽 9分鐘

           ·

          2021-06-12 17:40

          #Q1 = 和 := 的區(qū)別?

          答案:
          := 聲明+賦值
          = 僅賦值

          var foo int
          foo = 10
          // 等價于
          foo := 10

          #Q2 指針的作用?

          答案:
          指針用來保存變量的地址。
          例如

          var x =  5
          var p *int = &x
          fmt.Printf("x = %d", *p) // x 可以用 *p 訪問
          • ?* 運算符,也稱為解引用運算符,用于訪問地址中的值。

          • ?&運算符,也稱為地址運算符,用于返回變量的地址。

          #Q3 ?Go 允許多個返回值嗎?

          答案:
          允許

          func swap(x, y string) (string, string) {
          return y, x
          }

          func main() {
          a, b := swap("A", "B")
          fmt.Println(a, b) // B A
          }

          #Q4 Go 有異常類型嗎?

          答案:
          Go 沒有異常類型,只有錯誤類型(Error),通常使用返回值來表示異常狀態(tài)。

          f, err := os.Open("test.txt")
          if err != nil {
          log.Fatal(err)
          }

          #Q5 什么是協(xié)程(Goroutine)

          答案:
          Goroutine 是與其他函數(shù)或方法同時運行的函數(shù)或方法。Goroutines 可以被認為是輕量級的線程。與線程相比,創(chuàng)建 Goroutine 的開銷很小。Go應(yīng)用程序同時運行數(shù)千個 Goroutine 是非常常見的做法。

          #Q6 如何高效地拼接字符串

          答案:
          Go 語言中,字符串是只讀的,也就意味著每次修改操作都會創(chuàng)建一個新的字符串。如果需要拼接多次,應(yīng)使用 strings.Builder,最小化內(nèi)存拷貝次數(shù)。

          var str strings.Builder
          for i := 0; i < 1000; i++ {
          str.WriteString("a")
          }
          fmt.Println(str.String())

          #Q7 什么是 rune 類型

          答案:
          ASCII 碼只需要 7 bit 就可以完整地表示,但只能表示英文字母在內(nèi)的128個字符,為了表示世界上大部分的文字系統(tǒng),發(fā)明了 Unicode, 它是ASCII的超集,包含世界上書寫系統(tǒng)中存在的所有字符,并為每個代碼分配一個標準編號(稱為Unicode CodePoint),在 Go 語言中稱之為 rune,是 int32 類型的別名。

          Go 語言中,字符串的底層表示是 byte (8 bit) 序列,而非 rune (32 bit) 序列。例如下面的例子中 語 和 言 使用 UTF-8 編碼后各占 3 個 byte,因此 len("Go語言") 等于 8,當然我們也可以將字符串轉(zhuǎn)換為 rune 序列。

          fmt.Println(len("Go語言")) // 8
          fmt.Println(len([]rune("Go語言"))) // 4

          #Q8 如何判斷 map 中是否包含某個 key ?

          答案:

          if val, ok := dict["foo"]; ok {
          //do something here
          }

          dict["foo"] 有 2 個返回值,val 和 ok,如果 ok 等于 true,則說明 dict 包含 key "foo",val 將被賦予 "foo" 對應(yīng)的值。

          #Q9 Go 支持默認參數(shù)或可選參數(shù)嗎?

          答案:
          Go 語言不支持可選參數(shù)(python 支持),也不支持方法重載(java支持)。

          #Q10 defer 的執(zhí)行順序

          答案:

          • ?多個 defer 語句,遵從后進先出(Last In First Out,LIFO)的原則,最后聲明的 defer 語句,最先得到執(zhí)行。

          • ?defer 在 return 語句之后執(zhí)行,但在函數(shù)退出之前,defer 可以修改返回值。

          例如:

          func test() int {
          i := 0
          defer func() {
          fmt.Println("defer1")
          }()
          defer func() {
          i += 1
          fmt.Println("defer2")
          }()
          return i
          }

          func main() {
          fmt.Println("return", test())
          }
          // defer2
          // defer1
          // return 0

          這個例子中,可以看到 defer 的執(zhí)行順序:后進先出。但是返回值并沒有被修改,這是由于 Go 的返回機制決定的,執(zhí)行 return 語句后,Go 會創(chuàng)建一個臨時變量保存返回值,因此,defer 語句修改了局部變量 i,并沒有修改返回值。那如果是有名的返回值呢?

          func test() (i int) {
          i = 0
          defer func() {
          i += 1
          fmt.Println("defer2")
          }()
          return i
          }

          func main() {
          fmt.Println("return", test())
          }
          // defer2
          // return 1

          這個例子中,返回值被修改了。對于有名返回值的函數(shù),執(zhí)行 return 語句時,并不會再創(chuàng)建臨時變量保存,因此,defer 語句修改了 i,即對返回值產(chǎn)生了影響。

          #Q11 如何交換 2 個變量的值?

          答案:

          a, b := "A", "B"
          a, b = b, a
          fmt.Println(a, b) // B A

          #Q12 Go 語言 tag 的用處?

          答案:
          tag 可以理解為 struct 字段的注解,可以用來定義字段的一個或多個屬性。框架/工具可以通過反射獲取到某個字段定義的屬性,采取相應(yīng)的處理方式。tag 豐富了代碼的語義,增強了靈活性。

          例如:

          package main

          import "fmt"
          import "encoding/json"

          type Stu struct {
          Name string `json:"stu_name"`
          ID string `json:"stu_id"`
          Age int `json:"-"`
          }

          func main() {
          buf, _ := json.Marshal(Stu{"Tom", "t001", 18})
          fmt.Printf("%s\n", buf)
          }

          這個例子使用 tag 定義了結(jié)構(gòu)體字段與 json 字段的轉(zhuǎn)換關(guān)系,Name -> stu_name, ID -> stu_id,忽略 Age 字段。很方便地實現(xiàn)了 Go 結(jié)構(gòu)體與不同規(guī)范的 json 文本之間的轉(zhuǎn)換。

          #Q13 如何判斷 2 個字符串切片(slice) 是相等的?

          答案:
          go 語言中可以使用反射 reflect.DeepEqual(a, b) 判斷 a、b 兩個切片是否相等,但是通常不推薦這么做,使用反射非常影響性能。

          通常采用的方式如下,遍歷比較切片中的每一個元素(注意處理越界的情況)。

          func StringSliceEqualBCE(a, b []string) bool {
          if len(a) != len(b) {
          return false
          }

          if (a == nil) != (b == nil) {
          return false
          }

          b = b[:len(a)]
          for i, v := range a {
          if v != b[i] {
          return false
          }
          }

          return true
          }

          #Q14 字符串打印時,%v 和 %+v 的區(qū)別

          答案:
          %v 和 %+v 都可以用來打印 struct 的值,區(qū)別在于 %v 僅打印各個字段的值,%+v 還會打印各個字段的名稱。

          type Stu struct {
          Name string
          }

          func main() {
          fmt.Printf("%v\n", Stu{"Tom"}) // {Tom}
          fmt.Printf("%+v\n", Stu{"Tom"}) // {Name:Tom}
          }

          但如果結(jié)構(gòu)體定義了 String() 方法,%v 和 %+v 都會調(diào)用 String() 覆蓋默認值。

          #Q15 Go 語言中如何表示枚舉值(enums)

          答案:
          通常使用常量(const) 來表示枚舉值。

          type StuType int32

          const (
          Type1 StuType = iota
          Type2
          Type3
          Type4
          )

          func main() {
          fmt.Println(Type1, Type2, Type3, Type4) // 0, 1, 2, 3
          }

          參考 What is an idiomatic way of representing enums in Go? - StackOverflow

          #Q16 空 struct{} 的用途

          答案:
          使用空結(jié)構(gòu)體 struct{} 可以節(jié)省內(nèi)存,一般作為占位符使用,表明這里并不需要一個值。

          fmt.Println(unsafe.Sizeof(struct{}{})) // 0

          比如使用 map 表示集合時,只關(guān)注 key,value 可以使用 struct{} 作為占位符。如果使用其他類型作為占位符,例如 int,bool,不僅浪費了內(nèi)存,而且容易引起歧義。

          type Set map[string]struct{}

          func main() {
          set := make(Set)

          for _, item := range []string{"A", "A", "B", "C"} {
          set[item] = struct{}{}
          }
          fmt.Println(len(set)) // 3
          if _, ok := set["A"]; ok {
          fmt.Println("A exists") // A exists
          }
          }

          再比如,使用信道(channel)控制并發(fā)時,我們只是需要一個信號,但并不需要傳遞值,這個時候,也可以使用 struct{} 代替。

          func main() {
          ch := make(chan struct{}, 1)
          go func() {
          <-ch
          // do something
          }()
          ch <- struct{}{}
          // ...
          }

          再比如,聲明只包含方法的結(jié)構(gòu)體。

          type Lamp struct{}

          func (l Lamp) On() {
          println("On")

          }
          func (l Lamp) Off() {
          println("Off")
          }


          瀏覽 63
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情视频网站 | 麻豆传媒美少妇勾引管家 | 麻豆videos | 亚洲高清无码免费在线观看 | 91牛网站 |