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
", &a)
	fmt.Printf("p变量存储的指针地址: %x
", p)

	//使用指针访问值
	fmt.Printf("*p变量的值: %d
", *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空指针

//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
", a)
printf("pass_by_ref: %d
", 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(非指针)的已初始化(非零值)的值

    //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}
原文地址:https://www.cnblogs.com/konghui/p/10703595.html