• Golang学习(用代码来学习)


    type Circle struct {
    	radius float64
    	desc   string
    }
    
    //定义结构体里面的方法
    func (c Circle) getArea() float64 {
    	return 3.14 * c.radius * c.radius
    }
    
    //如果想要改变结构体里面的成员变量,就必须传入指针,否则的话是不生效的
    func (c *Circle) setRadius(val float64) {
    	c.radius = val
    }
    
    //因为没有传入指针,所以这里的Circle对象被拷贝了,因此不生效
    func (c Circle) setRadiusFake(val float64) {
    	c.radius = val
    }
    
    /*
    方法学习,其实就是类似于类里面的函数,但是go没有类这个东西
    */
    func method_test() {
    	print_start_seperator("method_test");
    	var cir Circle;
    	cir.radius = 12;
    	fmt.Printf("circle's area:%f 
    ", cir.getArea())
    
    	cir.setRadius(10)
    	fmt.Printf("after real setRadius[%f] circle's area:%f 
    ", cir.radius, cir.getArea())
    
    	cir.setRadiusFake(20)
    	fmt.Printf("after fake setRadius[%f] circle's area:%f 
    ", cir.radius, cir.getArea())
    	print_end_seperator();
    }
    
    /**
    没有指定大小,是切片,在go里面是指针传递
    */
    func slice_func(arr []int) {
    	for idx, val := range arr {
    		fmt.Printf("[slice_func]idx:%d val:%d 	", idx, val)
    	}
    	fmt.Println("")
    }
    
    /**
    指定了大小,是数组,在go里面是值传递
    */
    func arr_func(arr [5]int) {
    	for idx, val := range arr {
    		fmt.Printf("[arr_func]idx:%d val:%d 	", idx, val)
    	}
    	fmt.Println("")
    }
    
    /**
    修改array里面的值,由于数组是值传递,因此这里对原有的参数没有任何影响
    */
    func change_arr(arr [5]int, val int) {
    	for idx, _ := range arr {
    		arr[idx] = val * 10
    	}
    }
    
    /**
    切片是指针传递,因此这里的修改对原有值会有影响
    其实本质上这样的写法,切片也是值传递,只是因为在go中切片存储的结构体里面具体的数值是个指针,所以值传递
    也只是拷贝了这部分指针的地址,修改的是同一片内存,go中的切片存储的方式如下:
    type Slice struct{
    arr *int
    size int
    cap int
    }
    */
    func change_slice(arr []int, val int) {
    	for idx, _ := range arr {
    		arr[idx] = val * 10
    	}
    }
    
    /**
    工具函数,打印数组
    */
    func print_arr(arr [5]int) {
    	for _, val := range arr {
    		fmt.Printf("%d	", val)
    	}
    	fmt.Println("")
    }
    
    /**
    工具函数,打印切片
    */
    func print_slice(arr []int) {
    	if nil == arr {
    		return
    	}
    
    	for _, val := range arr {
    		fmt.Printf("%d	", val)
    	}
    	fmt.Println("")
    }
    
    /**
    工具函数,打印切片
    */
    func print_slice_str(arr []string) {
    	if nil == arr {
    		return
    	}
    
    	for _, val := range arr {
    		fmt.Printf("%s	", val)
    	}
    	fmt.Println("")
    }
    
    /*
    数组和切片学习,数组和切片在go中是两种完全不同的类型,不要搞混了。
    */
    func array_slice_test() {
    	print_start_seperator("array_slice_test")
    	arr := []int{5, 4, 3, 2, 1}
    	slice_func(arr)
    	//没有指定大小的参数只能传给没有指定大小的函数
    	//arr_func(arr)
    
    	arr2 := [5]int{10, 9, 8, 7, 6}
    	//slice_func(arr2)
    	arr_func(arr2)
    
    	//下面的数组虽然只是声明,因为指定了大小,所以默认初始化为0
    	var arr3 [5]int
    	for _, val := range arr3 {
    		fmt.Printf("val:%d 	", val)
    	}
    	fmt.Println()
    
    	//没有指定大小,是切片,在go里面和数组是完全不同的类型,所以arr3本质上是nil,for循环将不会执行
    	var arr4 []int
    	for _, val := range arr4 {
    		fmt.Printf("%d", val)
    		fmt.Println("I am not executed!!!!")
    	}
    
    	if nil == arr4 {
    		fmt.Println("arr4 is a nil!!!!!!!!!!!!!")
    	}
    
    	//数组是值传递
    	var arr5 [5]int = [5]int{0, 0, 0, 0, 0}
    	change_arr(arr5, 15)
    	fmt.Println("After changing the array...")
    	print_arr(arr5)
    
    	/**
    	本质上切片也是值传递,只是因为在go中切片存储的结构体里面具体的数值是个指针,所以值传递
    	也只是拷贝了这部分指针的地址,修改的是同一片内存,go中的切片存储的方式如下:
    	type Slice struct{
    	arr *int
    	size int
    	cap int
    	}
    	*/
    	var arr6 []int = []int{0, 0, 0, 0, 0, 0, 0}
    	change_slice(arr6, 15)
    	fmt.Println("After changing the slice...")
    	print_slice(arr6)
    
    	//使用数组进行切片的初始化
    	var arr7 = [5]string{"one", "two", "three", "four", "five"}
    	slice1 := arr7[:]
    	print_slice_str(slice1)
    
    	slice1 = arr7[1:3]
    	print_slice_str(slice1)
    	//slice获取的是原来数组的一段数组引用,因此这里的修改会在原数组上面体现到
    	slice1[0] = "new_two"
    	fmt.Printf("After assign to slice. arr7:%s  slice1:%s
    ", arr7, slice1) //After assign to slice. arr7:[one two new_two four five]  slice1:[two new_two]
    
    	//此时如果修改原数组呢?
    	arr7[1] = "newer_two"
    	//此时切片也生效了,也就是说,他们始终引用的是同一片地址
    	fmt.Printf("After assign to origin arr. arr7:%s  slice1:%s
    ", arr7, slice1) //After assign to origin arr. arr7:[one newer_two three four five]  slice1:[newer_two three]
    
    	//第一个参数为size,第二个参数为capacity
    	var slice2 = make([]int, 3, 10)
    	fmt.Printf("slice2.  size:%d  cap:%d
    ", len(slice2), cap(slice2))
    
    	//可以通过append来增加slice的数据,记住,这里要接受返回的值
    	slice2 = append(slice2, 1)
    	slice2 = append(slice2, 2, 3, 4)
    	fmt.Printf("After append. slice2:%d
    ", slice2) //[0 0 0 1 2 3 4]
    
    	//注意append函数是生成了一个新得切片,原来得切片对象不会有任何改变
    	slice2_bak := append(slice2, 10, 11, 12)
    	fmt.Printf("After append. slice2:%d   slice2_bak:%d
    ", slice2, slice2_bak) //After append. slice2:[0 0 0 1 2 3 4]   slice2_bak:[0 0 0 1 2 3 4 10 11 12]
    
    	var slice3 = make([]int, len(slice2), cap(slice2))
    	copy(slice3, slice2)
    	fmt.Printf("After copy slice. slice3:%d
    ", slice3)
    	//注意,一定要指明slice的长度,否则copy将没有任何效果
    	var slice4 []int
    	copy(slice4, slice2)
    	fmt.Printf("After copy slice. slice4:%d
    ", slice4) //[]
    
    	slice_append()
    	print_end_seperator()
    }
    
    /**
    slice里面一个需要注意的现象
    */
    func slice_append() {
    	//注意,这里指定了slice的cap为10
    	slice := make([]int, 5, 10)
    	for i := 0; i < 5; i++ {
    		slice[i] = i
    	}
    
    	slice1 := slice
    	slice_p := &slice
    	fmt.Printf("slice:%d  slice1:%d   slice_p:%d
    ", slice, slice1, *slice_p)
    	fmt.Printf("slice's addr:%p 
    ", &slice)
    
    	//接下来修改slice, 由于slice的cap为10,这里长度够,所以并没有申请新的内存,所以这里slice里面的数组地址没有变化,slice本身也不会变化
    	slice = append(slice, 10, 11, 12)
    	fmt.Printf("After append.  slice:%d  slice1:%d   slice_p:%d
    ", slice, slice1, *slice_p)
    	fmt.Printf("After append, slice's addr:%p 
    ", &slice)
    
    	//注意,这里指定了slice的cap为6
    	slice2 := make([]int, 5, 6)
    	for i := 0; i < 5; i++ {
    		slice2[i] = i
    	}
    
    	slice3 := slice2
    	slice2_p := &slice2
    	fmt.Printf("slice2:%d  slice3:%d   slice2_p:%d
    ", slice2, slice3, *slice2_p)
    	fmt.Printf("slice2's addr:%p 
    ", &slice2)
    
    	//接下来修改slice, 由于slice的cap为6,长度不够了,所以会申请新的内存,此时注意,只是slice结构体里面的数组地址发生了变化
    	//但是对于slice这个结构体本身,其地址并没有发生变化,所以看到的地址也没有变
    	fmt.Printf("slice.size:%d   slice.cap:%d
    ", len(slice2), cap(slice2))
    	slice2 = append(slice2, 10, 11, 12, 13, 14, 15, 16, 17)
    	fmt.Printf("After append.  slice2:%d  slice3:%d   slice2_p:%d
    ", slice2, slice3, *slice2_p)
    	fmt.Printf("After append, slice2's addr:%p 
    ", &slice2)
    }
    
  • 相关阅读:
    线程池
    多线程随笔
    注解随笔
    反射机制
    iO流
    FastDFS+docker建立分布式文件系统
    Java之Exception
    Java之String
    手写SpringMvc
    spring中一些常用注解的含义
  • 原文地址:https://www.cnblogs.com/seancheer/p/13164477.html
Copyright © 2020-2023  润新知