[TOC]golang
兵长:哟,最近在干啥呢api
胖sir:在看我以前的go基础学习资料呢,回顾一下数组
兵长:那给我分享一下呗,我也想回顾回顾安全
胖sir:用你的小手指点开你的手机,我来传给你数据结构
兵长:你信不信个人小手指能够带你飞整个峡谷 . . .并发
package main import "fmt" func main(){ //go语言中此处的花括号不能单独占一行,不然会报错 fmt.Println("hello world") }
下面列举了 Go 代码中会使用到的 25 个关键字或保留字:app
break | default | func | interface | select |
---|---|---|---|---|
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
除了以上介绍的这些关键字,Go 语言还有 36 个预约义标识符:ide
append | bool | byte | cap | close | complex | complex64 | complex128 | uint16 |
---|---|---|---|---|---|---|---|---|
copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new | nil | panic | uint64 |
println | real | recover | string | true | uint | uint8 | uintptr |
定义变量的三种方式函数
//字符串 可使用+ 进行拼接 fmt.Println("this is my func") fmt.Println("hello ,wolrd" + "xiaozhuzhu") //定义变量 var name string="xiaomotong" var age,tail int=24,170 fmt.Println(name, age , tail) fmt.Println(name) fmt.Println(age) fmt.Println(tail) //定义变量的三种方式 //1 var a int = 1 fmt.Println(a) //2 使用var定义变量,可是不定义类型,经过赋初值的方式,go编译器自动识别 var b = "hello" fmt.Println(b) //3 使用:=的方式来进行 新变量的定义,仅限于新变量 //:= 左侧若是没有声明新的变量,就产生编译错误 c := 20 fmt.Println(c) //c:=30 //报错,由于c已经不是新变量的 c=30 //正确,是一个正常的赋值操做 fmt.Println(c) c,d:=40,90 //这样是合法的 fmt.Println(c,d)
因式分解的方式,仅仅适用于定义全局变量学习
//因式分解的方式,仅仅适用于定义全局变量 var ( g_a int = 1 g_b,g_c int=1,2 )
空白标识符 _ 也被用于抛弃值,如值 5 在:_, b = 5, 7 中被抛弃。
_ 其实是一个只写变量,你不能获得它的值。这样作是由于 Go 语言中你必须使用全部被声明的变量,但有时你并不须要使用从一个函数获得的全部返回值。
//空白符 _,e := 2,3 fmt.Println(e)
//定义const常量 const width,height = 10,5 var area int=width*height fmt.Println("面积为", area) //50
const( unknow = 0 man = 1 woman = 2 ) println(unknow,man,woman) //0 1 2
const( a = "hello" b = len(a) c = unsafe.Sizeof(a) ) println(a,b,c) //hello 5 16
iota,特殊常量,能够认为是一个能够被编译器修改的常量。
iota 在 const关键字出现时将被重置为 0(const 内部的第一行以前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
iota 能够被用做枚举值:
//itoa的用法 const( g_a = iota g_b g_c g_d ) const( g_e = iota g_f = "hello" g_g g_h = iota g_i ) const( g_j = 1<<iota g_k g_l g_m ) println(g_a,g_b,g_c,g_d) println(g_e,g_f,g_g,g_h,g_i) println(g_j,g_k,g_l,g_m) //0 1 2 3 //0 hello hello 3 4 //1 2 4 8
go语言的运算符和C语言的运算符基本一致
算术运算符
关系运算符
逻辑运算符
位运算符
赋值运算符
其余运算符
if xxx { ... }
if xxx{ ... }else{ ... }
if xxx{ if xxx { ... } ... }
package main import "fmt" func main(){ grade:= 90 if grade >= 90{ println("优秀") }else if grade >=70 && grade <90{ println("良好") }else{ println("差") } var x interface{} //计算类型 switch i := x.(type){ case nil: fmt.Printf(" x 的类型 :%T\n",i) case int: fmt.Printf("x 是 int 型") default: println("未知") } }
select
相似于C语言中的select,用于多路IO复用
package main import "fmt" func main(){ //相似C语言中的for var sum int for i:=1;i<=10;i++{ sum +=i } fmt.Println(sum) //相似于while for sum >30{ sum -= 10 fmt.Println(sum) } //死循环 for { ... }
//for-each range 循环的方式 name := []string{"qqq","yyy"} for i,str:= range name{ fmt.Printf("%d -- %s\n",i,str) } //0 -- qqq //1 -- yyy ------------------------------------------------------------------------ str := []string{"北京", "天津", "山东"} //能够默认丢掉第二个返回值 for i := range str { fmt.Printf("%d -- %s\n", i, str[i]) }
go语言的函数,能够有多个返回值,其他和C语言没有什么区别
与C语言一致
思想和C语言一致,数组是固定长度的
切片是动态扩容的,相似于C++的vector
切片写法以下:
name := []string{"xiaomotong","pangsir"} nums :=[]int{1,2,3,4,5,6}
var ptr1 *int
var a int var ptr *int var pptr **int ptr = &a pptr = &ptr
var ptr [5]*int
go语言中的结构体变量,和结构体指针,访问结构体成员的时候,都是使用 点(.)来进行访问,以下:
//定义一个结构体 type info struct{ name string age int height int } //使用 var stu info stu.name = "xiaomotong" stu.age = 24 stu.height = 170 fmt.Println(stu.name,stu.age,stu.height) var stu2 *info = &stu stu2.name = "pangsir" stu2.age = 24 stu2.height = 160 fmt.Println(stu2.name,stu2.age,stu2.height)
Go 语言切片是对数组的抽象。
Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,能够追加元素,在追加时可能使切片的容量增大。
package main /* author:xiaomotong file:slice function:study slice for golang */ import "fmt" func main(){ //定义切片的方式 //一、使用var定义 var s1 = []int{1,2,3}; printInfo(s1); //二、定义空slice var s2 []int printInfo(s2); //三、使用:=定义 ss := []int{3,4,5,6} printInfo(ss); //四、使用make来定义 make([]type,len,cap) s3 := make([]int,2,3) printInfo(s3); //复制操做 s3[0] = 3 printInfo(s3); //覆盖整个slice s1 = s3 printInfo(s1); //apend 和 copy的使用 s3 = append(s3,6,7,8,9) printInfo(s3); //扩容 s4 := make([]int,len(s3),cap(s3) * 3) copy(s4,s3) printInfo(s4); //s[2:] println(s4[1:]) println(s4[:4]) println(s4[1:3]) fmt.Printf("s4[1:] = %v \n",s4[1:]) fmt.Printf("s4[:4] = %v \n",s4[:4]) fmt.Printf("s4[1:3] = %v \n",s4[1:3]) } func printInfo(s[]int){ fmt.Printf("len = %d, cap = %d, slic = %v\n",len(s),cap(s),s); }
Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。
在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
package main /* author:xiaomotong file:range function:study range for golang */ import "fmt" func main(){ //一、range 对于 数组、切片 s := []string{"apple","pen"} for i,value := range s{ fmt.Println(i,value) } //二、对于字符串 for i,value := range "hello"{ fmt.Println(i,value) } //三、range对于map集合 m := map[string]string{"name":"xiaopang","age":"25"} for i,value := range m{ fmt.Println(i,value) } //四、占位符_ sum := 0 nums := []int{1,2,3,4,5} for _,value := range nums{ sum += value } fmt.Println(sum) }
Map 是一种无序的键值对的集合。Map 最重要的一点是经过 key 来快速检索数据,key 相似于索引,指向数据的值。
Map 是一种集合,因此咱们能够像迭代数组和切片那样迭代它。不过,Map 是无序的,咱们没法决定它的返回顺序,这是由于 Map 是使用 hash 表来实现的。
//相似于key-value的形式 map[string]string m := map[string]string{"name":"xiaozhu","age":"15"} mm := make(map[string]string) countryCapitalMap [ "France" ] = "巴黎" countryCapitalMap [ "Italy" ] = "罗马" countryCapitalMap [ "Japan" ] = "东京" countryCapitalMap [ "India " ] = "新德里"
delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key
delete(countryCapitalMap,"France")
Go 语言支持递归。但咱们在使用递归时,开发者须要设置退出条件,不然递归将陷入无限循环中。
递归函数对于解决数学上的问题是很是有用的,就像计算阶乘,生成斐波那契数列等。
递归算阶乘
package main import "fmt" func fabulaxiaomotong(n uint 64) (result uint64){ if n>0 { return fabulaxiaomotong(n-1)*n } return 1 } func main(){ fmt.Println("result : ",fabulaxiaomotong(15)) }
菲波拉契数列
func fabolaxiaomotong(n uint64)(result utin64){ if n<2{ return n }else{ return fabolaxiaomotong(n-2)+fabolaxiaomotong(n-1) } }
Go 语言提供了另一种数据类型即接口,它把全部的具备共性的方法定义在一块儿,任何其余类型只要实现了这些方法就是实现了这个接口
package main import "fmt" //接口 type phone interface { call() show() } type xiaomi struct { name string ads string } type huawei struct { name string ads string } //接口实现 func (x xiaomi) call() { fmt.Println("phoneName :", x.name) } func (x xiaomi) show() { fmt.Println("advertisement :", x.ads) } func (h huawei) call() { fmt.Println("phoneName :", h.name) } func (h huawei) show() { fmt.Println("advertisement :", h.ads) } func main() { x := xiaomi{"mi note2", "for fire"} x.call() x.show() h := huawei{"hw p40", "your better phone"} h.call() h.show() }
Go 语言经过内置的错误接口提供了很是简单的错误处理机制。error类型是一个接口类型,这是它的定义:
package main import "fmt" //定义数据结构 type DivideError struct { devidee int devider int } //错误处理实现Error()接口 func (de *DivideError) Error() string { strdata := ` error,divide is zero dividee is %d divider is zero ` return fmt.Sprintf(strdata, de.devidee) } //实现功能接口 func Divide(dividee int, divider int) (result int, errMsg string) { if divider == 0 { data := DivideError{dividee, divider} errMsg = data.Error() return } else { return dividee / divider, "" } } func main() { a := 10 b := 0 result, err := Divide(a, b) if err != "" { fmt.Println(err) return } fmt.Printf("%d / %d == %d \n", a, b, result) }
Go 语言支持并发,咱们只须要经过 go 关键字来开启 goroutine 便可。goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。goroutine 语法格式:
package main import ( "fmt" "time" ) func say(s string) { var i int for i = 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } var num int = 0 //goroutine 是线程不安全的 func countNum() { var i int for i = 0; i < 10; i++ { time.Sleep(5 * time.Millisecond) num++ } } func main() { //go say("hello") //say("world") go countNum() countNum() fmt.Println(num) }
package main import "fmt" //不带缓冲的 通道 func getSum(s []int, c chan int) { sum := 0 for _, value := range s { sum += value } c <- sum } func getSum2(c chan int, n int) { x, y := 0, 1 var i int for i = 0; i < n; i++ { c <- x x, y = y, x+y } close(c) //关闭通道 } func main() { //不带缓冲的 通道 // s := []int{3, 5, -2, 3, 4, 7, 1, 1, 1} // c := make(chan int) // go getSum(s[:3], c) // go getSum(s[3:6], c) // go getSum(s[6:], c) // x, y, z := <-c, <-c, <-c // fmt.Println(x, y, z, x+y+z) //带缓冲的通道 c := make(chan int, 10) go getSum2(c, cap(c)) for value := range c { fmt.Println(value) } }
本身调用别人的包或者本身的包,如上目录结构
mylib.go
package mylib func Add(a, b int) int { return a + b }
main.go
package main import ( "fmt" "mystudy/mylib" ) func main() { fmt.Println(mylib.Add(2, 3)) }
以上为本期所有内容,若有疑问能够在评论区或后台提出你的疑问,咱们一块儿交流,一块儿成长。
好家伙要是文章对你还有点做用的话,请帮忙点个关注,分享到你的朋友圈,分享技术,分享快乐
技术是开放的,咱们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
做者:小魔童哪吒