GO基础知识总结

这篇博客总结了Go语言的基础知识,包括变量声明、fmt包的使用、常量的iota用法、字符串处理、循环和控制流、数组和切片、map的特性、指针和内存管理、函数及方法、并发和通道。还提到了goroutine和channel的使用,以及并发安全和模板渲染等核心概念。
摘要由CSDN通过智能技术生成

1.函数外只能声明变量,不能写表达式 (函数外的声明必须以关键字var const func等开头)
2.fmt.print()正常打印 fmt.println()末尾会加换行符 fmt.printf() 可以用占位符 %s字符串占位符 %v打印值 %b 打印二进制int类型 %d打印十进制int %o 打印八进制 %x打印16进制 %T打印数据类型
fmt.Sprintf()格式化字符串并赋给新变量,我们在编写SQL语句的时候要用到,可以避免SQL注入

3.方法中可以快速声明变量赋值 a:=1
4.声明的全局变量可以不用,剩下的声明了就必须得用 声明变量 var a int = 1(var a =1 类型推导)
5.布尔型默认值是false,且布尔型不能强制转换类型
6.声明常量的iota用法 在const关键字出现时将被重置为0。const中每新增一行常量声明将使iota计数一次
7.var a = 1.1415926 声明一个float型 默认是64位的float
8.单引号里只能放1个字或者字母 数字 专业名称叫字符 例如’1’ ‘我’ ‘s’
9.字符串是双引号的 例如 “aaaaa” 遇到路径 \a\s\a等 要用\转义 要写成这样 “\a\s\a"才会原样输出
10.反引号是指原样输出 比如遇到路径 \a\s\a 等 \a\s\a 是原样输出 不用转义
11.len() 计算字符串长度
12.a:=“aaaa” b:=“bbbbb” 字符串拼接 c:=a+b 或者 c:=fmt.Sprintf(”%s%s",a,b)
13.字符串更改 GO中的字符串的更改只能通过强制的类型转换然后更改,更改完了再转换成string类型 这个操作是会重新分配内存并赋值字节数组的 类型的强制转换T() T是要转换的类型
注意:英文字符要把字符串转换为 []byte类型,然后像数组下标更改那样改动但别忘了字符要用单引号 中文字符要把字符串转换为[]rune类型,再像数组一样修改,如果字符串中有英文和中文 那要把字符串转成rune[]类型更改
14.-- ++自加和自减 在Go中不算运算符
15.if一定要与左大括号在一行 else也是 另外else也要与if的右大括号在一行
16.switch语句的fallthrough语法 可以使走完一个case 强制走下一个case 最后一个case 不能使用fallthrough 否则会报错
17.数组是定长的 声明数组 var a =[2]int 方括号里必须有定长值 数组长度和类型都相等才相等 当然也可以这样声明 var a = […]int{1,2,3}来自动推导个数
18 for循环除了常规的使用外 还可以利用range关键字 例如 for index,value:=range a{} 来循环 index代表下标 value代表值 如果不需要index下标,可以使用匿名变量_来扔掉他
19.切片的增加与删除都要利用append这个函数 增加append(a,后面是要增加的值) 删除append(a[0:5])//只要前下标为0到5的
20.切片的copy()函数 copy(数据源切片,要复制的切片) 要复制的切片是独立出数据源切片的,是复制到另外一个切片空间,他数据的更改不会影响到源数据切片
21.map集合是无序的,其底层是又散列表(hash)实现的 遍历map时的元素顺序与添加键值对的顺序无关。声明map make(map[int]string,5,5)或者s:=map[int]string{}
22.map的有序打印的方式 是把key取出来放入切片中 利用sort包的方法对切片内容进行排序,然后循环拿出map的内容 sort.Ints–对int类型排序 sort.Strings–对string类型排序 sort.Float64s 对float浮点数排序
23.如果切片是剪切的像这样b:=a[0:2]切片的容量就是底层数组剩余的容量(从切片头到数组尾的容量),如果是自己声明并赋值的话像这样b:=[]int{1,2,3} 容量等于长度等于3
24.函数的关键字 func 函数的参数由参数名和类型组成,多个参数用逗号分割,返回值也由返回值变量和返回值类型组成多个可由逗号分割,返回值也可只写返回类型, 注意,调用有返回值的函数时,可以不接收其返回值。
25.go的类型写在变量后面,无论是变量还是方法中的参数都是这样
26.defer关键字 如果有多个 最后那个defer最先执行(逆序) 其他的没有defer关键字的 按正常顺序从上到下执行
27.go 中的return 不是原子操作 分为给返回值赋值和RET指令(返回返回值) defer操作在赋值和RET指令之间 先赋值再defer操作再RET指令(如果有defer操作的话) defer 后如果是函数,函数的参数会算好赋值进去,延迟的只是defer的函数
28.append()方法必须赋值给原来的变量,如果添加的值大于原来底层数组的大小,会重新指向新的底层数组
29.切片不能使用===来对比两个切片是否一样 切片只能与nil相比较
30.取内存地址操作符&和取值操作符 * 是一对互补操作符,
&从变量当中取出变量的内存地址,* 从地址中取出地址指向的值
31.对变量进行取值(&)操作,可以获得这个变量的指针变量 这个指针变量的值是指针地址,对指针变量进行取值( * )操作可获得指针变量指向的原变量的值
32.go对于引用类型的变量我们在声明时不光要声明类型还要为他准备好内存空间,用new和make两个方法
33.内置函数new()用于声明指针变量,标准用法a:=new(int)a就是int类型,a的值是内存地址 如果是*int类型的话 *a的初始值会是0
34.内置函数make()用于声明slice(切片)map,和channel(通道)
35.类型定义 type NewInt int 类型别名 type MyInt = int 用类型定义的新类型声明的变量打印出的变量类型是NewInt(新类型) 用类型别名的类型声明的变量打印出的变量类型还是int(原类型)
36.结构体也可以说为是自定义类型 标准 type aaa struct{name string,age int,school string} 实例化结构体 var a aaa 赋值操作 a.name=“名字” 打印name字段 fmt.Printf(“名字是%v”,a.name)
37.指针结构体 a:=new(aaa)或者 a:=&aaa{}
38.结构体占用一块连续的内存
39.在实际应用中尽量使用指针结构体,避免内存的浪费
40.painc()方法抛出错误直接终止程序,recover()方法 主要做一些错误抛出后,程序关闭前的一些清除占用资源的事,这两个函数一般搭配defer使用,且defer一定要写在painc()之前,painc()搭配recover()方法使用
41.方法和接收者,方法是一种作用于特定类型的函数(结构体就是一种自定义类型—当然任何一种类型都可以咱们先以结构体为例,实例化结构体才能调用方法,这里的结构体我们叫做接收者,或者可以说我们的所有类型在这里都可以叫做接收者)
具体看链接 https://blog.csdn.net/w05980598/article/details/80875427
42.结构体继承基于结构体嵌套,如果B结构体中有A结构体,那么B初始化之后也能调用A的接收者方法
43.函数名,方法名,类型名,变量名 (首字母大写对包外可见,首字母小写对包外不可见) 有点类似php的public private Protected
44.interface是一种类型,里面包含着接口定义的一个或多个方法, 接口变量能够存储所有实现了该接口的实例(一个实例实现了接口中的所有方法,我们就称这个实例实现了该接口)
45.值接收者实现接口,不管是值结构体变量还是指针结构体变量都可以赋值给接口变量,指针接收者实现接口,只能把指针结构体变量赋值给接口变量(注意点)
46.一个类型可以实现多个接口,多个类型可以实现同一个接口
47.空接口可以作为函数的参数类型,和返回值类型(空接口代表了所有类型)
48.类型断言

 var x interface{
   } 
 x="hello,北京欢迎您"
 v,ok:=x.(string) //作为类型断言 语法 x.(T)
 if ok{
   
  fmt.Printf("类型断言成功")
 }else{
   
  fmt.Printf("类型断言失败")
 }

49…并发goroutine(协程) go的并发是属于用户态线程,用法是在函数调用前写上go关键字,类似 go aaa(),多个协程执行是没有顺序的
在这里插入图片描述
示例

package main

import (
	"fmt"
	"sync" //为了告诉主协程 开启协程的个数,等协程程执行完再关闭
)
//函数前加go关键字  开启一个协程(用户态线程)
//并发编程需要snyc函数

var wg sync.WaitGroup//sync.WaitGroup是结构体

func hello()  {
   
	fmt.Printf("hello")
	wg.Done()//协程完成的标志
}

func main()  {
   
	wg.Add(100) //标记牌
	for i:=0; i<=100; i++{
   
		go hello()
	}

	fmt.Printf("完成")
	wg.Wait()//等待
}

50.go还提供了channel通道来支持goroutine 之间的通信问题,与协程搭配使用,通道分为有缓冲和无缓冲的通道

有缓冲的通道示例

a:=make(chan int,1) //设置容量1

无缓冲通道示例

a:=make(chan int)//不指定容量

有缓冲和无缓冲通道的区别

无缓冲的通道只有在有人接收值的时候才能发送值,原因是无缓冲通道的发送操作会阻塞(注意点),直到有人接收

示例

func jieshou(ch chan int){
   
	fmt.Printf(ch)
}
fun main(){
   
	//实例化一个无缓冲通道
	ch:=make(chan int)
	go jieshou(ch) //开启一个接收协程  必须写在ch<-1 前面,不然 ch<-1会死锁
	ch<-1
}

有缓冲的通道则不需要担心这一点

func main(){
   
    ch:=make(chan int,1)
    ch<-11
    fmt.Printf("发送成功")
}

51.channel注意点
避免在接收端关闭通道,因为不知道发送端是否再发数据,尽量发送端关闭,接收端判断

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值