golang的自学 其他部分基本内容(代码学习框架)

                                                                        说

       因为在学习过程中使用工具是vscode,在学习过程中是边学边实践,所以 笔记和心得 都在代码中体现(源码和注释)

       下面记录是单纯学了的几个部分,还有几个模块还没有记录,包括goroutine和反射reflect等

                                                                        const

package main

func main() {

	const length int = 100
	//	fmt.Println(length)

	const (
		bs  = 12923
		df  = "sjd"
		sfh = 'w'
	) //类似声明变量的 var(...) 写法

	const (
		//可以在const()里添加一个关键字iota,每行的iota都会累加 1,第一行的iota的默认值是0
		//作枚举使用
		//并且:iota只能配合const()一起使用
		a = iota // 可以 进行与iota的运算,比如:a=10*iota,则 b = 20,c = 30
		b
		c
	)
	//	fmt.Println(a, b, c)
	//iota默认是0,所以fmt的输出的值为: 0 1 2
	const (
		aa, bb = iota + 1, iota + 2 //iota = 0
		cc, dd                      //iota 每执行一行const中的代码,iota++
		ee, ff                      //iota = 2

		gg, hh = iota * 2, iota * 3 //iota = 3
		ii, jj                      //iota = 4
	)
	//	fmt.Println(aa, bb, cc, dd, ee, ff, gg, hh, ii, jj)
}

                                                                

                                                                   func_use 

package main

import "fmt"

//貌似目前发现,go语言是不支持函数重载的

func hanshu() int {
	//fmt.Print("NIHAOYA")
	//fmt.Print("NIHAO")
	return 111
}
func hanshu1(kjj int, fd string) int { //注意给进来参的声明:类型在后
	//fmt.Print("NIHAOYA")
	//fmt.Print("NIHAO")
	return 111
}

func hanshu_ret2_nonename() (int, int) { //返回多个返回值,匿名的

	return 666, 777
}

func hanshu_ret3_name() (r1 int, r2 int) { //与之相同作用但是不同写法(返回类型相同的) 可以写成:(r1,r2 int)
	r1 = 100
	r2 = 300
	return
}

func main() {

	fmt.Println(hanshu()) //函数调用

	//fmt.Println(hanshu_ret2_nonename()) //双返回值调用

	ret1, ret2 := hanshu_ret2_nonename()
	fmt.Println(ret1, ret2)

	fmt.Println(hanshu_ret3_name())
}

                                                                        array

package main

import "fmt"

func printArray(myArr [4]int) { //固定的长度,这里是拷贝的值,而非像 slice 的引用
	for i := 0; i < 4; i++ {
		fmt.Println(myArr[i])
	}
	myArr[0] = 99999
}

func main() {

	myArray := [4]int{3, 4, 5, 6}

	var intarry1 [10]int
	for i := 0; i < len(intarry1); i++ {
		intarry1[i] = i
		fmt.Println(intarry1[i])
	}

	for index, value := range myArray {
		fmt.Println("index = ", index, "value = ", value)
	}
	fmt.Println("---------------------------------------------------")

	printArray(myArray)
	printArray(myArray) //这里看看在函数里面更改了值是否是改变的 myArray 的值
	//发现确确实实改变不了,从而更证明了  再传固定长度的数组时,他使用的是拷贝的思想;但在slice中是用的引用的思想

	/*
		printArray(intarry1)

	        ERROR: cannot use intarry1 (type [10]int) as type [4]int in argument to printArray
		传固定长度的函数,无法传数组长度不相匹配的数组,intarry1 是长度为10的数组,所以他会报错

	*/
}

                                                                        

                                                                        defer

package main

import "fmt"

func main() {
	//defer 用法关键字
	defer fmt.Println("main func ends") //defer非常相似于 c++ 中的析构函数,也就是 函数结束之前触发
	//析构作用

	//可有多个 defer执行,并且: defer是利用栈的规则,即先压进去后出去
	defer fmt.Println("1")
	defer fmt.Println("2")
	//run后结果就应该为 2  1  main func ends
	fmt.Println("start")
	fmt.Println("a ...interface{}")

	//另外的 defer 还可以用于调用函数: 将函数压栈调用

	// 比如:
	// defer func1()
	// defer func2()
	// defer func3()
	// 就应该先调用 func3 后 func2 ,最后func3

	/*
		另外的:
		当一个函数有return 的函数时,要知道先执行完return 后再执行defer
		如:
		func aaa int (){
			fmt.Println("10086")
		}

		func bbb int (){
			fmt.Println("12315")
			return 0
		}

		func ggg int (){
			defer aaa()
			return bbb()
		}

		执行结果为 : 12315
					 10086



	*/
}

                            

                                                                      struct

package main

import "fmt"

type car struct {
	price int
	kind  string
	grade string
} // 没啥好说的 和c/c++没什么区别,除了命名方式

func changestruct(ff car) { //这边是传递进去了一个拷贝,而不是指针
	ff.grade = "iisuturate"
}

func changestruct_pointer(ff *car) { //这边是传递进去了一个指针,而不是拷贝
	ff.grade = "iisuturate"
}

func main() {
	var osprism car
	osprism.grade = "A"
	osprism.price = 1230000
	osprism.kind = "super car"

	fmt.Println(osprism)
	changestruct(osprism)
	fmt.Println(osprism)

	changestruct_pointer(&osprism)
	fmt.Println(osprism)

	var astr car //类的实例化 astr
	astr.grade = "12333321"

}

                                                               struct_extends

package main

import "fmt"

type Parentclass struct {
	name string
	age  int
}

func (this *Parentclass) facelike() {
	fmt.Println("parentclass_old man face")
}

func (this *Parentclass) printall() {
	fmt.Println(this.age, this.name)
}

type sonclass struct {
	Parentclass //写上这个就是声明: son这个类继承于 parentclass

	likewhat string //新成员变量

}

func (this *sonclass) facelike() {
	fmt.Println("sonclass_young man face")
}

func (this *sonclass) changelike() {
	this.likewhat = "swimming"
}

func main() {
	par1 := Parentclass{
		name: "baba",
		age:  10,
	}
	son1 := sonclass{ //注意一下这里:如何实例化子类的对象
		Parentclass{
			name: "erzi",
			age:  2,
		}, //逗号别忘了
		"basketball", //并且另外这里直接跟着对应的值 --- 对应顺序
	}
	par1.printall()
	son1.printall() //未重写

	par1.facelike()
	son1.facelike() //子类重写过

	//另外的,如果子类不够方便,也可以先定义出来一个对象
	//如:
	var dd sonclass
	dd.name = "dog"
	dd.likewhat = "qiuqiu"
	dd.age = 4
	dd.printall()
}

                                                                 struct_packed

package main

import "fmt"

type book struct {
	page  int //page 首字母是小写,所以是私有成员
	title string
}

type BoOK struct { //如果类名的首字母大写,表示其他包也能够访问
	//如果类内属性的首字母大写,表示该属性是公开的,若是小写,则是只对类内开放
	theme string
	word  int

	Report string
}

//封装模式

func (this BoOK) Pinn() { //	//如果函数首字母大写,表示该函数是公开的(针对其他包),若是小写,则是只对包内开放

}

func (this book) cha_name() { // 拷贝类型
	this.page = 100
	this.title = ""
}
func (this *book) cha_name_pointer() { // 指针类型,传进来就是改变原对象的相关属性
	this.page = 680
	this.title = "只有我才能带领我们走向胜利"
}

func main() {
	var moo book
	mo := book{
		page:  12,
		title: "only we can destroy it",
	}
	mo.cha_name()
	moo.cha_name()
	fmt.Println(mo.page, mo.title)
	fmt.Println(moo.page, moo.title)

	mo.cha_name_pointer()
	moo.cha_name_pointer()
	fmt.Println(mo.page, mo.title)
	fmt.Println(moo.page, moo.title)

	mo.page = 878
	fmt.Println(mo.page)

	//总而言之,若包名和类名或者方法名的首字母是大写时,其他包也可访问,若为小写的话,那么只能是在包内访问
}

                                                                        slice

package main

import "fmt"

func printArray(myArray []int) {
	for index, value := range myArray {
		fmt.Println(index, value)
	}

	// slice 非拷贝,是引用
	myArray[0] = 888889 //通过 run 的结果可以知道,这里可以对 myArray 的值进行改变,so : 切片不是对数组的拷贝,而是对数组的引用。
}

func printArray_(myArray []int) {
	for _, value := range myArray { //与上面的那个原函数作区分,比如说对某个变量不关心的时候,可以用 _ 来代替,代表不需要这个变量
		fmt.Println(value)
	}
}

func main() {
	myArray := []int{133, 285, 34} //动态数组,切片 slice

	fmt.Printf("the type of myArray = %T\n", myArray)

	printArray(myArray)
	printArray_(myArray)
}

                                                              slice_use_usual

package main

import "fmt"

func main() {
	//-------------------------------------与普通的声明相同的初始化,都默认是 0 ,与c的随机值不同
	slice1 := []int{1, 2, 3, 4}

	fmt.Println(slice1)

	var slice2 []int        //类似c++中的 int* slice2 ;
	slice2 = make([]int, 4) //等价于 slice2 = new int [4]

	//上面也可以直接整合
	//比如说:
	var slice3 = make([]int, 4) // int *slice3 =new int [3]
	//make (数组类型,数组长度)

	slice4 := make([]int, 6)
	fmt.Println(slice2)
	fmt.Println(slice3)
	fmt.Println(slice4)
	var slice5 []int
	if slice5 == nil { // nil = NULL(c++)
		fmt.Println("空")
	} else {
		fmt.Println("非空")
	}

	//slice 的开辟和追加  ---- 引入容量

	slice6 := make([]int, 4, 7) // 这里意思是  slice6  是开辟一个容量为 7 的一个空间,但是先只占用 4 个单位
	fmt.Println("the len of slice6 = ", len(slice6), "the cap of slice6 = ", cap(slice6), slice6)
	//slice6 的全部信息

	//append  追加函数

	slice6 = append(slice6, 8989)
	fmt.Println(slice6)      //[0 0 0 0 8989]
	fmt.Println(len(slice6)) //  len = 5  容量cap不会变

	/*
		append 函数在追加时,当容量与长度相同时,即容量已经满的时候,因为slice是一个动态的切片
		故有: 系统为 slice 分配一个与之前相同的容量大小,有上面的条件来看,当7个已经全部占满了的时候
		系统会再给分配 7 个容量

	*/
	slice6 = append(slice6, 467, 789)
	fmt.Println("the len of slice6 = ", len(slice6), "the cap of slice6 = ", cap(slice6), slice6)
	slice6 = append(slice6, 33)
	fmt.Println("the len of slice6 = ", len(slice6), "the cap of slice6 = ", cap(slice6), slice6)
	//此时,len = 8, cap = 14

	/*
		切片的截取
	*/
	SP := make([]int, 0, 4)
	SP = append(SP, 67444, 100, 1115500000)
	sl1 := SP[0:2]   //意义是: 截取到 SP 的 [0,2) 注意闭区间和开区间
	fmt.Println(sl1) //  取到的是  下标 0 , 1 的元素 对应的是 [67444 100]

	//*****************************************不要忘记了  slice  是指针应用的对象
	//如:
	jk := make([]int, 0, 4)
	jk = append(jk, 55, 66, 77, 88)
	jp := jk[:3]
	fmt.Println(jp)
	fmt.Println(jk)
	jk[2] = 0
	fmt.Println(jp)
	fmt.Println(jk)
	jp[2] = 222
	fmt.Println(jp)
	fmt.Println(jk)
	//slice 是指针, 故更改一个,两个输出的结果都会变化

	//copy函数,是开辟一个新的空间,复制一个副本
	copy1 := make([]int, 5)
	copy(copy1, jk)
	fmt.Println(copy1)
	/*
		run 的结果是
		[55 66 222 88]    // jk
		[55 66 222 88 0]  // copy1
		由此可见,哪怕两个的容量不相同也是可以的  当副本容量大于原件时
		副本会把原件原封不动的复制过来,多出来的空间不做处理
	*/
	copy2 := make([]int, 2)
	copy(copy2, jk)
	fmt.Println(copy2)
	/*
		run 的结果是
		[55 66 222 88]    // jk
		[55 66]  // copy2
		由此可见,哪怕两个的容量不相同也是可以的  当副本容量小于原件时
		副本会将自己的空间复制填满,但是少的部分不做处理(填满自己空间就结束)
	*/
}

                                                                    pointer

package main

import "fmt"

func swap1(a int, b int) {
	temp := a
	a = b
	b = temp
}

func swap2_pointer(a *int, b *int) {
	temp := *a
	*a = *b
	*b = temp
}

func main() {
	a := 100
	b := 200
	swap1(a, b)
	fmt.Println("a= ", a, "b= ", b)
	swap2_pointer(&a, &b)
	fmt.Println("a= ", a, "b= ", b)

	var e int = 9000
	var p *int
	p = &e
	fmt.Println(p)  //得到的是 e 的地址
	fmt.Println(&e) //输出 e 的地址
	fmt.Println(*p) //得到的是 e 的值

	//二级指针:
	var pp **int
	pp = &p
	fmt.Println(**pp) // *pp 对应的 p 的值,再来一级,就是对应 *p 的值
}

                                                                map_announce

package main

import "fmt"

//map 就是键值对,一个东西对应着一个值

func main() {
	var map1 map[string]string //方式一声明 map 类型
	map1 = make(map[string]string, 3)
	if map1 == nil {
		fmt.Println("空")
	} else {
		fmt.Println("非空")
	}
	map1["ni hao"] = "xie xie"
	map1["qing wen"] = "nin shuo ?"
	fmt.Println(map1)

	/*
		方式二 声明 map 类型
	*/

	map2 := make(map[int]string) // := 方式
	map2[0] = "ni shi"
	map2[1] = "gou ma"
	map2[2] = "?"
	fmt.Println(map2)

	map3 := map[int]int{ // { } 方式,别忘了加上逗号和冒号,这种事不需要make的方式
		1: 7,
		2: 8,
		3: 9,
	}
	fmt.Println(map3)

}

                                                                     map_use

package main

import "fmt"

func forprint(mpo map[int]string) { //传进来的类型其实还是指针类
	for key, value := range mpo {
		fmt.Println(key, value)
	}

	//尝试改变 键值对
	mpo[2] = "你是good"
}
func main() {

	mapo := map[int]string{
		1: "ii",
		2: "oo",
		3: "pp",
	}
	forprint(mapo)

	fmt.Println("__________________________")

	for key, value := range mapo {
		fmt.Println(key, value)
	}
	//由此可知map传出去到函数还是传递指针,而非拷贝
}

                                                                   interface 

package main

import "fmt"

type compute interface {
	add()
}

//具体的类

type cal struct {
	kind string
}
type cpu struct {
	speed int
	many  int
}

func (this *cal) add() {
	fmt.Println(this.kind)
	fmt.Println("the main is cal")
}
func (this *cpu) add() {
	fmt.Println(this.many)
	fmt.Println(this.speed)
	fmt.Println("the main is cpu")
}

func showfunc_interface(inter compute) {
	inter.add() // 多态
}

func main() {

	// 接口的第一种方式
	var inte compute
	inte = &cal{"qwer"}
	inte.add()
	inte = &cpu{5000, 4}
	inte.add()

	// 接口的第二种方式
	// 在函数中直接传个接口参数,
	// 多态

	fmt.Println("============================")

	showfunc_interface(inte)

	inte = &cal{"啊啊嘿嘿"}

	showfunc_interface(inte)

}

                                                              interface_use

package main

import "fmt"

// 万能接口空接口

type innt interface {
	ss()
}
type aa struct {
	yy string
	zz int
}

func (this *aa) ss() { //采用接口时访问不能带 返回类型
	fmt.Println("ss=========aa ...interface{}")
}

func testinter(arr interface{}) { //这里传进来的东西(interface()代表的意思是指万能接口,可以使任何数据类型)

	fmt.Println(arr)

	fmt.Printf("%T\n", arr)

	/*
		类型断言:
	*/

	value, kk := arr.(aa) // 如果是括号里的类型,那么 value = as,如果不是的话 value不赋值(还是默认)
	//   arr的类型是否是 ()中的类型  如果是的话,kk = 1
	if kk {
		fmt.Println("kk == 1 , is int")
		fmt.Println(value)
	} else {
		fmt.Println("kk == 0 , isn't int")
	}

}

func main() {

	testinter(3.14)
	testinter(3)

	//字符

	testinter('B')

	//字符创传入

	testinter("QWWEE")

	//结构体传入

	var rout aa
	rout.zz = 76777554123
	rout.yy = "uii"
	testinter(rout) // 类型 : main.aa

	//接口类传入

	var inb innt
	inb = &aa{"23223", 134}

	testinter(inb) // 类型:*main.aa

}

                                                                        pair

package main

import "fmt"

type aastr struct {
	a int
}
type intaa interface {
	funac()
}
type intbb interface {
	funac()
}

func (this *aastr) funac() {
	
	fmt.Println("a ...interface{}")

}
func ttpair(as interface{}) {
	value, kk := as.(int) ///  核心部分在这

	/*
		其实他的中心思想是
		pair: < type,value >
		类型断言

		如果是括号里的类型,那么 value = as,如果不是的话 value不赋值(还是默认)
	*/
	fmt.Println(as)
	fmt.Println(value)
	fmt.Println(kk)

}
func main() {
	var rr aastr
	rr.a = 9

	rainter := &rr.a

	ttpair(*rainter)
	fmt.Println("--------------------------------") //---------------------------------------
	h := aastr{775}

	ttpair(h)

	var kk intaa //实例化一个接口 kk
	kk = &h      //kk = &aastr{}

	var ll intbb //实例化一个接口 ll

	ll = kk.(*aastr) // 因为pair相同,所以kk和ll可以直接赋值过来
	fmt.Println(ll)
	ttpair(ll)
	ttpair(h)

}

                        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值