zoukankan      html  css  js  c++  java
  • 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}
  • 相关阅读:
    netcore3.0使用Session
    docker redis使用
    协变和逆变
    HashTable、Dictionary、ConcurrentDictionary三者区别
    设计模式-行为型-解释器模式
    设计模式-行为型-备忘录模式
    jq实现批量全选与反选
    call()和apply()的用法及区别,看这个例子就明白了
    谈谈对闭包的理解
    export,import和export default的区别
  • 原文地址:https://www.cnblogs.com/konghui/p/10703595.html
Copyright © 2011-2022 走看看