Go入门
变量
var a,b *int 变量声明 bool,string,uint,byte,float,complex 在go语言中所有的东西都是被初始化的 string = nil 不知名类型声明 var level =1,在编译的时候会初始化类型 批量格式定义
var (
a int
b string
c [ ] float32
)
i:=1 最简单的模式 只能定义在内部 conn,err := net.Dial(“tcp”,“127.0.0.1”) 这样也是可以重新定义conn1,err,两个中只要有一个不同就行 不想接受就是可以为匿名变量 conn,_ 下划线就是匿名变量 全局变量的声明必须以var关键字开头,如果想在外部包中使用全局变量的首字母必须大写 就是在main 外部定义 var int global func sum(a int,b int) int{} var is bool go的值比较非常严格 byte 就是char var mystr01 string var mystr02 [5]byte = [5]byte{1,2,3,4,5} 字符串长度len 中文字符串长度 utf8.RunCountInString(s) 字符串拼接直接用加号就行 另外一种拼接方式
var StringBuilder bytes. Buffer
stringBuilder. WriteString ( s1)
stringBuilder. WriteString ( s2)
直接索引对rune无效 string([]rune(mystr)[6]) 对中文进行遍历需要使用range的方式进行遍历
for _ , s:= range str{
}
postion:= strings. Index ( value, "s" )
类型转换
go语言不存在隐式类型转换所有的转换必须是显示声明的 int(value)强制转化 不同类型转化会发生错误 bool => int 就是会发生错误 golang语言的字符串是不可变的 所以先转化为[]byte(string)[1] = 1然后再去修改其中的一位
常量
const name string = “nihao” iota 常量生成器 第一个iota会被置为0
指针
%p代表指针的格式化 &取地址 *取内容 创建指针 prt :=new(string) 创建一个字符串的指针 flag是用来执行命令的 堆:用来存放进程中被动态分配的内存段,大小不固定 栈:就是用来存放局部变量 比较快
类型别名
type rune = int32 这个就是别名 type mybool bool 这个时类型定义 有什么差别呢? 在查看类型时候别名返回的就是原来的类型,但是定义返回的是当前定义的类型
关键字
字符串和其他类型的转换
str := "1"
intv, _ := strconv. Atoi ( str)
fmt. Println ( "%T" , intv)
intv1 := 1
strv := strconv. Itoa ( intv1)
fmt. Println ( "%T" , strv)
strf := "3.1415"
stof, _ := strconv. ParseFloat ( strf, 64 )
fmt. Println ( stof)
strconv. FormatFloat ( )
控制台标准输入输出
数组
Go语言中的数组的长度是固定的 var arr [10]int
var arr [ 10 ] int
fmt. Println ( arr)
for index, value := range arr {
fmt. Println ( index, value)
}
arr1 := [ 2 ] int { 1 , 2 }
arr3 := [ ... ] int { 1 , 2 , 3 }
fmt. Println ( arr1, arr3)
var arrmore [ 10 ] [ 10 ] int
fmt. Println ( arrmore)
arrmore1 := [ 2 ] [ 2 ] int { { 10 , 1 } , { 1 , 5 } }
fmt. Println ( arrmore1)
切片
和数组差不多,不过是长度是不确定的,每个都将数组作为底层数组,切片是引用类型,左闭右开 a[:] a[1:3] a[:3] 声明一个切片 var name []int ,
var arrmore [ 10 ] [ 10 ] int
fmt. Println ( arrmore)
arrmore1 := [ 2 ] [ 2 ] int { { 10 , 1 } , { 1 , 5 } }
fmt. Println ( arrmore1)
var sle [ ] int
l := len ( sle)
fmt. Println ( l)
sle = append ( sle, 1 )
mkt := make ( [ ] int , 10 )
fmt. Println ( mkt)
arrrr := [ ] int { 10 , 20 , 30 , 40 , 50 }
arrrrc := [ ] int { 10 , 2 , 58 , 8 }
fmt. Println ( arrrr, arrrc)
map
var mymap map [ string ] int
mymap2 := map [ string ] int { "nihao" : 1 , "buhao" : 2 }
fmt. Println ( mymap, mymap2)
fmt. Println ( mymap[ "nihao" ] )
mmap := make ( map [ string ] string , 10 )
fmt. Println ( mmap)
mms := make ( map [ string ] [ ] int )
mms2 := make ( map [ string ] * [ ] int )
mms[ "name" ] = [ ] int { 1 , 2 , 3 }
mms[ "555" ] = [ ] int { 5 , 2 , 3 }
fmt. Println ( mms, mms2)
for k, v := range mms {
fmt. Println ( k, v)
}
var mysyncmap sync. Map
mysyncmap. Store ( "key" , "value" )
mysyncmap. Store ( "key2" , "value2" )
mysyncmap. Load ( "key2" )
mysyncmap. Range ( func ( key, value interface { } ) bool {
fmt. Println ( key, value)
return true
} )
nil
nil 是不能进行比较 nil==nil 不同的值nil对应的大小是不一样的
new 和make
if else
if 1 == 1 {
fmt. Println ( "true" )
}
if x:= 100 ; x> 10 {
fmt. Println ( "x" )
}
for
for i := 0 ; i < 20 ; i++ {
fmt. Println ( i)
}
for {
break
}
for a> 100 {
goto bTag
}
break bTag:
for range
forragnge := make ( map [ string ] string )
forragnge[ "a" ] = "a"
forragnge[ "b" ] = "b"
for i, v := range forragnge {
fmt. Println ( i, v)
}
switch
a := 1
switch a {
case 1 :
fmt. Println ( "1" )
case 2 , 3 , 4 :
fmt. Println ( "2,3,4" )
}
switch {
case a== 2 :
fmt. Println ( "a==2" )
fallthrough
case a== 3 :
fmt. Println ( "a==3" )
}
goto
标签 name: 使用 goto name 使用goto处理错误
break continue
break 也可以跳出一个代码块 也可以和goto一样使用 continue 就是跳过本次 也可以和goto一样使用
函数
func max ( n1, n2 int32 ) ( int32 , string ) {
if n1 > n2 {
return n1
}
return n2, "nihao"
}
func funarg ( fn func ( ) int ) int32 {
return int32 ( fn ( ) )
}
func funcr ( ) ( ni string , hao string ) {
ni = "hello"
hao = "world"
return
}
参数 map,slice,chan,指针,interface默认是引用的方式进行传递 多个参数 args 本质上就是一个切片 返回一个闭包 那么里面的变量的值都是被持有的 那么里面的值每一个次都是不会被清空的 延迟调用 defer defer 不能直接执行 要放到匿名函数中 不然就是会出现问题 defer 在闭包内使用到的变量 会保存上下文用到的变量
错误处理
panic 遇到panic() ,就会终止 然后执行defer语句 再报告异常信息 然后推出gorotine 如果再defer中使用了revocer()函数,就会捕获醋无哦信息,是该错误信息终止报告 recover() 可以捕获到异常 延时调用中的错误,可以被后续的延时调用捕获,单只可以捕获最后一个
defer func ( ) {
if err := recover ( ) ; err != nil {
fmt. Println ( err)
}
} ( )
panic ( "error!" )
结构体
type my_struct struct {
name string
id int
x int
y int
}
var mys1 my_struct
mys1. x = 1
mys1. y = 2
mys := my_struct{ id: 1 , name: "nihao" , x: 1 , y: 2 }
fmt. Println ( mys)
ins := new ( my_struct)
ins. id = 1
类
type bag struct {
name string
goods [ ] string
}
func ( b * bag) GetGoods ( ) string {
return b. goods[ 0 ]
}
type bag struct {
name string
}
type Big struct {
bag
}
bb := Big{ bag{ "11" } }
接口
type AnimalIF interface {
Sleep ( )
GetName ( ) string
SetName ( string )
}
当你的struct去实现了接口就是实现了所有的方法 就相当于你实现了这个接口 这个就是非侵入式 一个类型可以实现多个接口 空接口 var int interface{} 断言
v, ok := ink. ( int )
fmt. Println ( v, ok)
I/O操作
Reader
reader := strings. NewReader ( "askjdfk sadfkjsad fasdfjk sdf" )
p := make ( [ ] byte , 8 )
for {
n, err := reader. Read ( p)
if err == io. EOF {
fmt. Println ( "读完了" , n)
break
}
fmt. Println ( p[ : n] )
}
文件操作api
create, _ := os. Create ( "test.txt" )
n, err := create. Write ( [ ] byte ( "hello world" ) )
if err != nil {
return
}
fmt. Println ( n)
create. Close ( )
var rr [ 32 ] byte
rr := make ( [ ] byte , 32 )
open, _ := os. Open ( "test.txt" )
open. Read ( rr)
fmt. Println ( rr)
os. Remove ( "test.txt" )
bufio 带缓冲区的文件读写
file, _ := os. OpenFile ( "test.txt" , os. O_APPEND, 0777 )
writer := bufio. NewWriter ( file)
for i := 0 ; i < 10 ; i++ {
builder := strings. Builder{ }
builder. WriteString ( "hello" )
builder. WriteString ( strconv. Itoa ( i) )
builder. WriteString ( "\n\r" )
s := builder. String ( )
writer. WriteString ( s)
}
writer. Flush ( )
reader:= bufio. NewReader ( file)
for {
line, _ , err := reader. ReadLine ( )
}
ioutil
file, err := os. ReadFile ( "test.txt" )
if err != nil {
}
fmt. Println ( string ( file) )
os. WriteFile ( "test2.txt" , [ ] byte ( "sdafasdf" ) , 0777 )
readFile, err := os. ReadFile ( "test2.txt" )
if err != nil {
}
fmt. Println ( string ( readFile) )
goroutine
func test ( ) {
fmt. Println ( "test" )
}
func main ( ) {
go test ( )
fmt. Println ( "main groutine" )
}
runtime包
runtime.Gosched() 再次重新分配一下任务 runtime.Goexit() 退出携程 runtime.GOMAXPROCES(1) 设置核心数
channel
var ch chan int 创建一个int型的通道 声明完成需要make才能使用 make(chan 元素类型,[缓冲区大小]) ch:=make(chan int,10) 操作 :发送,接受,关闭 发送和接受使用 <- 这个符号 发送 ch<-10 把10发送金桔 接受 x:=<-ch 关闭通道 close(ch) ,通道可以被垃圾回收机制给回收,对一个关闭的通道发送数据就会导致panic 无缓冲的channel 无缓冲的通道必须要存在接受者才能发送 无缓冲会阻塞
func rec ( ch chan int ) {
temp:= <- chan
fmt. PrintLn ( temp)
}
func main ( ) {
ch:= make ( chan int )
rec ( ch)
ch<- 10
fmt. PrintLn ( "发送者" )
}
func main ( ) {
ch:= make ( chan int , 1 )
ch<- 1
}
如何判断通道已经被关闭了 使用for range 就可以判断channel是否关闭 关闭了for range就是退出循环了 单向通道
var dan chan <- int = make ( chan int )
func counter ( out chan <- int ) {
out<- 10
}
func chu ( in <- chan int ) {
temp:= <- in
}
select 可以同时相应多个通道的操作 select 反正是看谁先
select {
case <- chan1:
case chan1<- :
default :
}
func test ( ch chan int ) {
select {
case ch<- 1 :
fmt. p ( "写" )
default :
}
}
并发安全和锁
互斥锁 var lock sync.Mutex lock.Lock() lock.Unlock() 同一时间只能够保证有一个进入临界区 读写互斥锁 当一个goroutine获得读锁 其他来也可以获得读 不可以获得写 当加上一个写锁 读和写都无法执行 sync.RWMutex 加锁涉及到内核态的转变 消耗比较高 基本数据类型 可以使用原子操作 sync/atomic atomic
Golang 调度器
Go的协程
g携程 只占几kb m线程 p管理本地的队列 M线程通过P 去操作G ,p会认为是cpu操作的核心数,GOMAXPROCES个数 线程想要运行就要先从p去获取携程
调度策略
网络编程
socket
就是封装了tcp/ip协议 只要调用socket就可以轻松实现tcp ip编程
TCP编程
面向连接,可靠的,基于字节流的通讯协议,因为是面向连接的,数据像流水一样传输,会存在黏包问题 使用net包 net.Listen(“tcp”,“127.0.0.1:20000”) net包也可以作为服务器的客户端 发起一个连接
UDP编程
实时性比较好 net.ListenUDP(“udp”,&net.UDPAddr{ IP:net.IPv4(0,0,0,0)//监听所有 Port:3000, })
HTTP编程
websocket
需要安装第三方包 go get -u -v github.com/gorilla/websocket 所有文件要一起运行 https://blog.csdn.net/qq_30614345/article/details/140083133
MYSQL
引入mysql驱动 _ “github.com/go-sql-driver/mysql” 在传递值的时候只有指针、切片、映射、通道和接口是默认传递地址的
func init ( ) {
sql. Open ( "mysql" , "root:root@tcp(localhost:3306)/go_table" )
DB. Exec ( "insert into user() values(?,?,?)" , username, sex, e)
rows, err = DB. Query ( "select * form user where id = ?" , id)
for rows. Next ( ) {
}
con, err:= DB. Begin ( )
_ := Db. commit ( )
_ := Db. rollback ( )
}
redis
“github.com/go-redis/redis/v8”
Go泛型
func IntOrFloats[ K comparable, V int64 | float64 ] ( m map [ K] V) V{
}
type fanxing interface {
int | float64 | string
}
func IntOrFloats[ K comparable, V fanxing] ( m map [ K] V) V{
}
多模块工作目录
再包含两个项目的大目录下 go work init ./fly-falsh 随便那个都行 go work use ./common 两个都加入
模糊测试