Golang - 複合類型

Golang - 複合類型

1. 指針

  • go語言中指針是很容易學習的,比C中容易的多,它能夠更簡單地執行一些任務
  • 與變量相似,使用前須要聲明,使用&符號能夠取內存地址
  • 聲明指針的格式:
    • var 指針變量名 *指針類型

指針的使用數組

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func main() {
    //聲明變量
    var a int = 20

    //聲明指針變量
    var p *int
    p = &a

    //十六進制
    fmt.Printf("a變量的地址是: %x\n", &a)
    fmt.Printf("p變量存儲的指針地址: %x\n", p)

    //使用指針訪問值
    fmt.Printf("*p變量的值: %d\n", *p)
}


//a變量的地址是: c042052080
//p變量存儲的指針地址: c042052080
//*p變量的值: 20

經過指針修改變量數據結構

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func main() {
    //定義變量
    var num int = 10
    fmt.Println(&num)
    var ptr *int

    //指針賦值
    ptr = &num
    //經過指針修改num
    * ptr = 20
    fmt.Println(num)
}

//0xc042052080
//20

go空指針app

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func main() {
    var ptr *int
    fmt.Println("ptr的值爲:", ptr)

    //判斷空指針
    if ptr == nil{
        fmt.Println("是空")
    }
}

//ptr的值爲: <nil>
//是空

值傳遞和引用傳遞函數

void pass_by_val(int a){
a++;
}

void pass_by_ref(int& a){
a++;
}

int main() {
int a = 3;

pass_by_val(a);
printf("pass_by_val: %d\n", a)
printf("pass_by_ref: %d\n", a)
}

答案:3,4

值傳遞:學習

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func swap(a, b int){
    a, b = b, a
}

func main() {
    a, b := 3, 4
    swap(a, b)
    fmt.Println(a, b)
}

// 3  4

go引用傳遞:指針

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func swap(a, b *int){
    *a, *b = *b, *a
}

func main() {
    a, b := 3, 4
    swap(&a, &b)
    fmt.Println(a, b)
}

// 4  3

2. new()和make()

  • new()用來分配內存,但與其餘語言中的同名函數不一樣,它不會初始化內存,只會將內存置零
  • make(T)會返回一個指針,該指針指向新分配的,類型爲T的零值,適用於建立結構體
  • make()的目的不一樣於new(),它只能建立slice、map、channel,並返回類型爲T(非指針)的已初始化(非零值)的值code

    //package 聲明開頭表示代碼所屬包
    package main
    
    import "fmt"
    
    func main() {
        p :=new([]int)
        fmt.Println(p)
    
        //[]int切片
        //10: 初始化10個長度
        //50: 容量爲50
        m :=make([]int, 10, 50)
        fmt.Println(m)
    
        m[0] = 10
        (*p)[0] = 10
        fmt.Println(p)
    }

3. 數組

聲明變量:對象

var 數組名[數組長度] 數組類型

聲明和初始化數組:內存

//package 聲明開頭表示代碼所屬包
package main

import "fmt"


func main() {
    //數組長度不讓變化
    //定義int類型數組
    var arr1 [5]int

    //:=聲明並賦值
    arr2 := [3]int{1, 2, 3}

    //能夠省略大小
    arr3 := [10]int{2, 4, 6, 8, 10}
    fmt.Println(arr1, arr2, arr3)

    //定義二維數組
    var grid [4][5]int
    fmt.Println(grid)
}

//[0 0 0 0 0] [1 2 3] [2 4 6 8 10 0 0 0 0 0]
//[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

數組是值類型仍是引用類型?

package main

import "fmt"

//傳入數組,修改元素
func printArr(arr [5]int)  {
   //修改一個元素
   arr[0] = 100
   for i,v := range arr{
      fmt.Println(i,v)
   }
}

func main() {
   //定義數組
   var arr1 [5]int

//:=聲明並賦值
   arr2 := [3]int{1, 2, 3}
   //能夠省略大小
   arr3 := [...]int{2, 4, 6, 8, 10}
   fmt.Println(arr1, arr2, arr3)

   //printArr(arr1)
   //報錯
   //printArr(arr2)
   printArr(arr3)

   //打印原始值
   fmt.Println()
   fmt.Println(arr3)
}

4. slice

  • 數組的長度在定義以後沒法再次修改,go語言提供了數組切片(slice)來彌補數組的不足
  • 建立切片的各類方式

    //package 聲明開頭表示代碼所屬包
      package main
    
      import "fmt"
    
      func main() {
          //聲明空切片
          var s1 []int
    
          //:=聲明
          s2 :=[]int{}
    
          var s3 []int = make([]int, 0)
          s4 :=make([]int, 0, 0)
          fmt.Println(s1, s2, s3, s4)
      }
    
    
      [] [] [] []

.

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func main() {
    //定義數組
    arr :=[...]int{0, 1, 2, 3, 4, 5, 6, 7}

    //切片取值
    fmt.Println(arr[2:6])
    fmt.Println(arr[:6])
    fmt.Println(arr[2:])
    fmt.Println(arr[:])
}


//[2 3 4 5]
//[0 1 2 3 4 5]
//[2 3 4 5 6 7]
//[0 1 2 3 4 5 6 7]

go切片能夠向後擴展, 但不能向前擴展

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func main() {
    //定義數組
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    s1 := arr[2:6]
    fmt.Println(s1)
    s2 := s1[3:5]
    fmt.Println(s2)
    
    //切片添加元素
    s3 := append(s2,10)
    fmt.Println(s3)
    fmt.Println(arr)

    s4 := append(s3,11)
    fmt.Println(s4)
    fmt.Println(arr)
    s5:= append(s4,12)
    fmt.Println(s5)
    fmt.Println(arr)
}

//[2 3 4 5]
//[5 6]
//[5 6 10]
//[0 1 2 3 4 5 6 10]
//[5 6 10 11]
//[0 1 2 3 4 5 6 10]
//[5 6 10 11 12]
//[0 1 2 3 4 5 6 10]

內建函數copy()

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func main() {
    //切片
    data := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    s1 := data[8:]
    s2 := data[:5]
    fmt.Println(s1)
    fmt.Println(s2)

    //將第二個拷貝到第一個裏
    copy(s2, s1)
    fmt.Println(s2)
    fmt.Println(data)
}

//[8 9]
//[0 1 2 3 4]
//[8 9 2 3 4]
//[8 9 2 3 4 5 6 7 8 9]

5. Map

  • Map 是go內置的數據結構,是一種無序的鍵值對的集合,能夠經過key快速找到value的值
  • 定義Map:
    • var 變量名 map[key的數據類型] value的數據類型
    • 建立map

      //package 聲明開頭表示代碼所屬包
          package main
      
          import "fmt"
      
          func main() {
              //聲明map
              var mmp map[int]string
              fmt.Println(mmp == nil)
      
              //m2和m3是等價的
              m2 := map[int]string{}
              m3 :=make(map[int]string)
              fmt.Println(m2, m3)
      
              m4 :=make(map[int]string, 10)
              fmt.Println(m4)
          }
      
          //true
          //map[] map[]
          //map[]

初始化map

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

func main() {
    //1. 定義同時初始化
    var m1 map[int]string = map[int]string{1:"超哥", 2:"最帥"}
    fmt.Println(m1)

    //2. 自動推導類型 :=
    m2 :=map[int]string{1:"超哥", 2:"最帥"}
    fmt.Println(m2)
}

//map[1:超哥 2:最帥]
//map[1:超哥 2:最帥]

鍵值操做

//package 聲明開頭表示代碼所屬包
package main

func main() {
    m1 :=map[int]string{1:"111",2:"222"}
    
    //修改
    m1[1]="1111"
    //追加
    m1[3]="333"
}

6. 結構體

  • go語言沒有class,只是個結構體struct
  • 結構體定義:
    • type 結構體名 struct{}
  • 結構體初始化

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

//定義學生結構體
type Student struct {
    id int
    name string
    sex byte
    age int
    addr string
}

func main() {
    //1.順序初始化
    var s1 Student = Student{1,"約漢",'f',18,"bj"}
    fmt.Println(s1)
    s2 := Student{2,"接客",'m',20,"sh"}
    fmt.Println(s2)
    //s3 := Student{3,"擼死",'m',25}

    //2.指定初始化成員
    s4 := Student{id:4,age:26}
    fmt.Println(s4)
    fmt.Println(s4.id)

    //3.結構體做爲指針變量初始化
    var s5 *Student = &Student{5,"接客",'f',20,"sh"}
    fmt.Println(s5)
    //指針類型訪問變量
    //go底層本身實現了轉換,下面2種均可以取指針對象的屬性
    fmt.Println((*s5).id)
    fmt.Println(s5.id)

    s6 := &Student{6,"接客",'m',20,"sh"}
    fmt.Println(s6)
}

//{1 約漢 102 18 bj}
//{2 接客 109 20 sh}
//{4  0 26 }
//4
//&{5 接客 102 20 sh}
//5
//5
//&{6 接客 109 20 sh}

7. 結構體參數

結構體能夠做爲函數參數傳遞

//package 聲明開頭表示代碼所屬包
package main

import "fmt"

type Student struct {
    id   int
    name string
    sex  string
    age  int
    addr string
}

//定義傳遞學生對象的方法
func tmpStudent(tmp Student) {
    //修改id
    tmp.id = 250
    fmt.Println("tmp=", tmp)
}

//定義傳遞指針類型的對象的方法
func tmpStudent2(p *Student) {
    //修改id
    p.id = 249
    fmt.Println("tmp2=", p)
}

func main() {
    var s Student = Student{1, "接客", "female", 20, "sz"}
    tmpStudent(s)
    fmt.Println("main s =", s)
    //傳遞指針地址
    tmpStudent2(&s)
    fmt.Println("main s2=", s)
}

//tmp= {250 接客 female 20 sz}
//main s = {1 接客 female 20 sz}
//tmp2= &{249 接客 female 20 sz}
//main s2= {249 接客 female 20 sz}
相關文章
相關標籤/搜索