Go語言學習查缺補漏ing Day3

恆生LIGHT雲社群發表於2021-12-06

作者:ReganYue

來源: 恆生LIGHT雲社群

Go語言學習查缺補漏ing Day3

零、前言

因為筆者基礎不牢,在使用Go語言的時候經常遇到很多摸不著頭腦的問題,所以筆者下定決心好好對Go語言進行查漏補缺,本【Go語言查缺補漏ing】系列主要是幫助新手Gopher更好的瞭解Go語言的易錯點、重難點。希望各位看官能夠喜歡,點點贊、關注一下唄!

一、結構體的比較問題

我們先來看一段關於結構體的比較的程式碼:

package main


import "fmt"

func main() {
  struct1 := struct {
      age int
      name string
      sex bool
  }{age: 18, name: "搏達", sex:false}
   
  struct2 := struct {
      age int
      name string
      sex bool
  }{age: 21, name: "Regan Yue", sex:true}
   
  if struct1 == struct2 {
      fmt.Println("struct1 == struct2")
  }

  struct3 := struct {
      age int
      people map[string]bool
  }{age: 31, people: map[string]bool{"搏達": false}}
   
  struct4 := struct {
      age int
      people map[string]bool
  }{age: 21, people: map[string]bool{"ReganYue": false}}
   
  if struct3 == struct4{
      fmt.Println("struct3 == struct4")
  }
}

你覺得編譯時會報錯嗎?

image-20211121193059286

image-20211121193143297

啊這,出大問題。它說包含map的結構體不能被比較。

是的,只有包含bool型別、數值型、字串、指標、陣列等型別的結構體才能比較,而包含slice、map、函式其中任一項的結構體均不能做比較。

還有幾點值得注意的是:

  1. 結構體之間只能比較它們是否相等,而不能比較它們的大小。

  2. 只有所有屬性都相等而屬性順序都一致的結構體才能進行比較。

二、透過指標變數訪問成員變數的幾種方式

先看這段程式碼:

package main


import "fmt"

func main() {
  s1 := struct {
      name string
      age int64
  }{name:"Regan",age:21}
  s2 := &s1
  fmt.Println(s2.name)
  fmt.Println((*s2).name)
  fmt.Println((&s2).name)
}

你覺得哪裡會報錯?

image-20211121194638463

哦!是(&s2).name有點問題.....

因為&是取地址符,*是指標解引用符。所以將指標解引用才能訪問到成員變數。

你會好奇為什麼指標不解引用也能獲取成員變數嗎?其實是進行解引用了,這就是我們GO語言的強大之處了,它能夠自動進行解引用,但是遺憾的是,只能解引用乙級指標,如果是多級指標,就得靠你自己了。

三、型別別名和型別定義的區別

package main


import "fmt"

type Int1 int
type Int2 = int

func main() {
  var i = 0
  var i1 Int1 = i
  var i2 Int2= i
  fmt.Println(i, i1, i2)
}

是不是一眼就看出來問題所在了?

不過他們放在一起,你能馬上分別哪個是型別別名,哪個是型別定義嗎?

type Int1 int

是定義了基於int型別建立了一個新型別,而

type Int2 = int

是將Int2作為int型別的別名。

所以將會報如下錯誤:

image-20211121201235626

這是因為Go是強型別語言,所以我們需要將int強制轉換Int1型別就可以透過編譯了。

四、切片的一個注意事項

package main


import "fmt"

func main() {
  a := []int{7, 8, 9}
  fmt.Printf("%+v\n", a)
  fun1(a)
  fmt.Printf("%+v\n", a)
  fun2(a)
  fmt.Printf("%+v\n", a)
}
func fun1(a []int) {
  a = append(a, 5)
}
func fun2(a []int) {
  a[0] = 8
}

看一看執行結果:

[7 8 9]

[7 8 9]
[8 8 9]

什麼?!! 沒有append進去?這是因為append可能會導致記憶體的重新分配,我們就不能再確定append之前的切片與之後的切片是不是引用的相同的記憶體空間。

所以說這個執行fun1來append之後的切片a與外面的切片a不是同一個,所以檢視外面的a,可以發現外面切片的內容沒有改變。

五、Golang字串連線的幾種方式

package main


import (
  "bytes"
  "fmt"
  "strings"
)

func main() {
  str1 := "abc"
  str2 := "def"
  strs := []string{"Regan","Yue"}
  fmt.Println(str1+str2)
  sprintf := fmt.Sprintf("abc%s", "accc")
  fmt.Println(sprintf)
  join := strings.Join(strs, "-")
  fmt.Println(join)

  var buffer bytes.Buffer
  buffer.WriteString("hello")
  buffer.WriteString("world")
  fmt.Println(buffer.String())
}

這裡提到了四種連線字串的方式,第一種利用+號直接連線,第二種利用 fmt.Sprintf(),第三種是利用strings.Join(),第四種是利用buffer.WriteString()來進行字串連線。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70001864/viewspace-2845936/,如需轉載,請註明出處,否則將追究法律責任。

相關文章