go未入门学习记录
开发环境配置go1.12.17+goland
参考链接macos配置go语言以及goland开发环境
语法学习记录
package main
//kaiyu.liu@shopee.com golang学习笔记
//参考资料 https://www.kancloud.cn/itfanr/go-quick-learn/81636
//参考视频 https://www.bilibili.com/video/BV1eK4y1b7fj?p=14
import ("bufio""fmt""math""os""strings"
)//go中函数构造语法 func关键字 + 函数名 + 参数列表 + 返回值列表,返回值只有一个类型时括号可以省略
func foo()(string,int){return "1234",900
}//预先设置返回值的名字,可以直接return,支持多返回值
func slice_sum(arr []int) (sum int) {sum = 0for _, elem := range arr {sum += elem}return
}//go函数支持可变长参数,要求:可变长参数列表里数据类型相同以及可变长参数只能是函数的最后一个参数
func sum(base int, arr ...int) int {sum := basefor _, val := range arr {sum += val}return sum
}//闭包函数,类似于函数指针,将函数封装成一个变量,特性在于闭包函数对其外层的函数参数具有修改能力
func example() int{var arr1 = []int{1, 2, 3, 4, 5}var sum = func(arr ...int) int {total_sum := 0for _, val := range arr {total_sum += val}return total_sum}fmt.Println(sum(arr1...))return 0
}//递归函数 就那样没啥区别//go语言中的异常处理
//defer,在函数运行结束的时候再运行语句
func testDefer() {fname := "D:\\Temp\\test.txt"f, err := os.Open(fname)defer f.Close()if err != nil {os.Exit(1)}bReader := bufio.NewReader(f)for {line, ok := bReader.ReadString('\n')if ok != nil {break}fmt.Println(strings.Trim(line, "\r\n"))}
}
//panic&recover异常关键字,panic触发异常,cecover终止一场并返回传递给panic的值,配合defer一定会运行
func test_panic() {defer func() {msg := recover()fmt.Println(msg)}()fmt.Println("I am walking and singing...")panic("It starts to rain cats and dogs")
}func main(){fmt.Println("Hello World!")var name string //go变量声明 var 名字 类型var(a string = "111"b int = 111c bool = false)fmt.Println(a,b,c,name)fmt.Printf("%s1234%d\n",a,b)//变量类型推倒 类似autovar y = 200fmt.Println(y)//短变量声明,只能在函数内部aaa:=123fmt.Println(aaa)//匿名变量aaaa,_:=foo()fmt.Println(aaaa)//常量声明const pi float32 = 3.1415const(aaaaaa = 1000bbbbbccccc//默认与aaaaa一样)//枚举 遇到const初始化为0,const中每增加一行都会使我们iota加一,const(a_ = iota //0_ = iota //1c_ = 1000d_ = iota //3)const(_ = iotakb = 1<<(10*iota)mb = 1<<(10*iota))const(a__,b__ = iota+1,iota+2 //1,2c__,d__ = iota+1,iota+2 //2,3)//数据类型整型 浮点型 布尔型 字符串 数组 切片 结构体 函数 map 通道//int8 int16 int32 int64 uint8-16-32-64 uint8=byte int16 = short int64 = long//int 与 uint取决于操作系统为int32或int64//内置函数len()var a1 int = 10fmt.Printf("%d \n",a1)var a2 int = 077 //8进制 0开头fmt.Printf("%o \n",a2)var a3 int = 0xff //16进制 0x开头fmt.Printf("%x \n",a3)//var a4 int = 0b11 //2进制 0b开头//fmt.Printf("%x \n",a4) 1.13开始支持2进制fmt.Printf("%p \n",&a1) //%p表示16进制内存地址//float32 float64两个常量 math.MaxFloat32 math.MaxFloat64 %f打印fmt.Printf("%f \n",math.MaxFloat32)//go中无法将布尔值与其他类型转换//字符串utf-8编码// \n换行 \r回车 \t制表 \'单引号 \"双引号 \反斜杠fmt.Println("\"c:\\go\"")var s = `多行文本不用转义`fmt.Println(s)//字符串操作// 求长度len(s)//拼接字符串 a+bss := fmt.Sprintf("%s%s",s,s)fmt.Println(ss)//分割ret := strings.Split(ss,"行")fmt.Println(ret)//判断包含 返回布尔retBool := strings.Contains(ss,"行")fmt.Println(retBool)//前缀与后缀ret3 := strings.HasPrefix(ss,"多")ret4 := strings.HasSuffix(ss,"义")fmt.Println(ret3,ret4)//求子串的位置fmt.Println(strings.Index(ss,"行"))fmt.Println(strings.LastIndex(ss,"行"))//joinsss := []string{"11","22","33"}fmt.Println(strings.Join(sss,"-"))//byte与rune类型 分别表示单个的英文与中文,类似于chara_rune := '中'fmt.Println(a_rune)//输出编码b_rune := "as中"fmt.Println(len(b_rune)) //输出5 utf-8下一个中文占3字节for i:=0;i<len(b_rune);i++{fmt.Printf("%c\n",b_rune[i]) //中文会乱码}//for range循环 按照runefor _,v:=range b_rune{fmt.Sprintf("%c\n",v) //range循环返回两个,是索引+值}//字符串不能直接改变,转换为byte/rune在转换s1 := "big"s2 := []byte(s1)s2[0] = 'p'fmt.Println(string(s2))//流程控制 if else for switch goto 没有while循环if 3>2{fmt.Println("123")}else {fmt.Println("sas")}if age2:=100;age2>90 { //age2作用域仅在for循环内部fmt.Println("21")}age := 19for age>10{ //类似于while循环age--}for{//死循环if age>0 {break}}switch age{//只能写一个defaultcase 1 :fmt.Println("11")case 2 :fmt.Println("123")default:fmt.Println("asdas")}switch n:=7; n {case 1,3,5,7,9:fmt.Println("jishu")fallthrough //下穿,无条件地执行下一条case,case 2,4,6,8:fmt.Println("oushu")}//goto 跳出整个循环for i:=1;i<3;i++{for j:=1;j<3;j++ {if (i == 2 && j == 2) {goto label}}}label://运算符 +-*/ %求余 ++ 自增--自减//数组var xarray = [5]int{}var xarray1 = [5]int{1,2,3,4,5}var xarray2 = [5]int{}var xarray3 = [...]string{"11","22","33",}//多维数组 不赋值默认初始化为0var xyarray = [3][2]int{[2]int{1,2},[2]int{3,4},[2]int{5,6},}fmt.Println(xarray,xarray1,xarray2,xarray3,xyarray)//切片,切片长度可变,包括长度len()与容量cap()两个属性。一种声明+make,取数组切片var xsharp = make([]int,5) //cap5 len5var xsharp1 = make([]int,5,10) //cap10 len5fmt.Println(cap(xsharp),cap(xsharp1))//数组切片赋值var s_1 = xarray1[:3] //类似于py 包含下界不含上界fmt.Println(s_1)//append 函数可以将切片与某些元素组合,当数量超过容量,cap会变为2倍slice1 := []int{1,2,3,4,5,6}slice2 := make([]int,5,10)copy(slice2,slice1) //将slice1赋值给slice2,但由于slice2长度为5,所以结果为【1,2,3,4,5】//字典var x_map = map[string]string{"a":"apple","b":"banana","o":"orange",}//另一种定义以及初始化方式var x_map2 map[string]stringx_map2 = make(map[string]string)x_map2["a"] = "apple"x_map2["b"] = "banana"//x_map3 := make(map[string]string)for key,val := range x_map{fmt.Println(key,val)}fmt.Println(x_map["p"]) //会返回0,不存在的key值//判断map中是否存在某个值,返回val为键值,ok为key值是否存在的布尔值变量if val,ok := x_map["a"];ok{fmt.Println(val)}//map中删除元素 delete 删除不存在的key值时不会报错delete(x_map,"a")//指针,通过传指针改变主函数中的参数值var x_ptr *intx_val := 10x_ptr = &x_valfmt.Println(x_val)fmt.Println(x_ptr)fmt.Println(*x_ptr)//go中的new函数x_ptr_new := new(int) //申请了一个存储整形变量的内存,并将此地址赋值给了x_ptr_new*x_ptr_new = 10}//定义一个结构体
type Rect struct {width float64length float64//width, length float64}//结构体的方法不需要定义在结构体内部,通过fun后标识所属结构体
func (rect Rect) area() float64 {return rect.width * rect.length
}
//调用 rect.area()/*使用方法var rect Rectrect.width = 100rect.length = 200//或者按照定于顺序赋值var rect = Rect{100, 200}
*///结构体类型指针
func structptr() {var rect = new(Rect)rect.width = 100rect.length = 200fmt.Println("Width:", rect.width, "Length:", rect.length,"Area:", rect.area())
}func (rect *Rect) double_area() float64 {rect.width *= 2rect.length *= 2return rect.width * rect.length
}//使用指针改变结构体的值。此处不改变值加不加*都可,不太严格。。
func ptrana() {var rect = new(Rect)rect.width = 100rect.length = 200fmt.Println(*rect)fmt.Println("Double Width:", rect.width, "Double Length:", rect.length,"Double Area:", rect.double_area())fmt.Println(*rect)
}//结构体内嵌直接调用,类似于继承
type Phone struct {price intcolor string
}func (phone Phone) ringing() {fmt.Println("ringing")
}type IPhone struct {Phonemodel string
}func inner() {var p IPhonep.price = 5000p.color = "Black"p.model = "iPhone 5"p.ringing() //方法的继承与调用fmt.Println("I have a iPhone:")fmt.Println("Price:", p.price)fmt.Println("Color:", p.color)fmt.Println("Model:", p.model)
}//结构体内嵌间接调用,这种类似于把结构体的一个对象当作成员
type Phonep struct{price intcolor string
}type Myphone struct{phone Phonepmodel string
}func inner2() {var p Myphonep.phone.price = 5000p.phone.color = "Black"p.model = "iPhone 5"fmt.Println("I have a iPhone:")fmt.Println("Price:", p.phone.price)fmt.Println("Color:", p.phone.color)fmt.Println("Model:", p.model)
}//关键字interface 提供接口功能,其他类型只要实现这个方法就是实现了这个接口,不一定非要显式地声明。
//这难道是面向切面编程?跟java有点相似
type ppPhone interface {call()
}type NokiaPhone struct {
}func (nokiaPhone NokiaPhone) call() {fmt.Println("I am Nokia, I can call you!")
}type iiIPhone struct {
}func (iPhone iiIPhone) call() {fmt.Println("I am iPhone, I can call you!")
}
func testInterface() {var phone ppPhonephone = new(NokiaPhone)phone.call()phone = new(iiIPhone)phone.call()
}