Golang学习笔记01
变量的数据类型
整数数据类型
- 有符号类型 int8 int16 int32 int64
- 无符号类型 uint8 uint16 uint32 uint64
浮点数据类型
- float32 4字节
- float64 8字节
布尔型
package main import ( "fmt" ) func main() { var s = true fmt.Println(s) }
字符串
不可变:指的是字符串一旦定义好,其中字符的值不可以改变,如果输入特殊字符,字符串形式为反引号
(图片来源网络,侵删)package main func main() { var s1 = ` var s = true println(s)` println(s1) }
可以保留原有的输入的内容
类型转化
只能进行强类型转化,不支持自动类型转化,原有的类型不变,只是将数值转化
package main func main() { var a = 101 var b = string(a) println(b) }
注意:int64转化为int8时编译不会出错,但是数值会溢出
其他类型转化为String
使用Sprintf函数进行转化
package main import "fmt" func main() { //其他类型转化为String类型 //fmt.Sprintf()使用中需要注意转换的格式,int 为%d, float 为%f, bool为%t, byte 为%c var a int = 20 var b float64 = 12.456 var c bool = true var d byte = 'a' var stra, strb, strc, strd string stra = fmt.Sprintf("%d", a) strb = fmt.Sprintf("%f", b) strc = fmt.Sprintf("%t", c) strd = fmt.Sprintf("%c", d) //输出值的类型%T,占位符%v fmt.Printf("stra type is %T, value is %v \n", stra, stra) fmt.Printf("strb type is %T, value is %v \n", strb, strb) fmt.Printf("strc type is %T, value is %v \n", strc, strc) fmt.Printf("strd type is %T, value is %v \n", strd, strd) }
使用strconv函数进行转化
package main import ( "fmt" "strconv" ) func main() { var n1 int = 18 //参数:第一个参数:传入int64位的一个整数,第二个参数:你需要转化的进制数 var s1 = strconv.FormatInt((int64(n1)), 10) fmt.Printf("s1对应的类型是:%T,s1 = %q", s1, s1) println() //参数:第一个参数:需要转化的数,第二个参数:‘f’(-ddd.dddd),第三个参数:小数点的保留位数,第四个参数:转化为int64 var n2 float64 = 4.21 var s2 = strconv.FormatFloat(n2, 'f', 4, 64) fmt.Printf("s2对应的类型是:%T,s2 = %q", s2, s2) println() var n3 = true var s3 = strconv.FormatBool(n3) fmt.Printf("s3对应的类型是:%T,s3 = %q", s3, s3) } //运行结果: //s1对应的类型是:string,s1 = "18" //s2对应的类型是:string,s2 = "4.2100" //s3对应的类型是:string,s3 = "true"
string类型转化为其他类型
package main import ( "fmt" "strconv" ) func main() { var a = "123" var a1, err = strconv.ParseInt(a, 10, 64) fmt.Printf("类型是:%T,值是%v,%v", a1, a1, err) println() //非数字字符不能转化为int var b = "hello" var b1, err1 = strconv.ParseInt(b, 10, 64) fmt.Printf("类型是:%T,值是%v,%v", b1, b1, err1) println() var c = "true" var c1, _ = strconv.ParseBool(c) fmt.Printf("类型是:%T,值是%v", c1, c1) }
指针
package main func main() { var i int = 10 println("i的值", i) //指针类型 var ptr *int = &i println("i的地址", ptr) println("ptr的地址", &ptr) println("ptr指向的值", *ptr) } /* 输出结果: i的值 10 i的地址 0xc00005ff28 ptr的地址 0xc00005ff38 ptr指向的值 10 */
注意点
- 指针可以改变具体的值
- 指针变量接受的是地址
- 指针的地址不可以不匹配
流程控制语句
package main import "fmt" func main() { //流程控制语句 var a = 10 if a > 10 { fmt.Println(1) } else { fmt.Println(2) } //switch循环 switch 10 / 2 { case 1: println(1) case 2: println(2) default: println(3) } //for循环 for i := 0; i
goto用法
package main import "fmt" func main() { fmt.Println(1) fmt.Println(2) if 1 == 1 { goto label1 } fmt.Println(3) fmt.Println(4) label1: fmt.Println(5) }
函数
package main import "fmt" func main() { //调用 var res = sum(1, 2) fmt.Println(res) } func sum(a int, b int) int { return a + b }
首字母大写该函数可以被本包文件和其他包使用(public),首字母小写只能被本包使用(private)
通过地址交换两个数
package main import "fmt" func main() { //调用 var a = 10 var b = 20 fmt.Println(a, b) swap(&a, &b) fmt.Println(a, b) } func swap(a *int, b *int) { var t = *a *a = *b *b = t }
ps:go中不支持重载,支持可变参数
go函数可以作为一个数据类型,赋值给一个变量
package main import "fmt" func test(num int) { fmt.Println(num) } func main() { var a = test fmt.Printf("a的类型是%T,test的类型为%T \n", a, test) //a的类型是func(int),test的类型为func(int)10 a(10) //等价与test(10) }
自定义数据类型
package main import "fmt" func main() { //自定义数据类型:相当于起别名 type myInt int var num1 myInt = 10 //num1的类型是main.myInt,num1的值为10 fmt.Printf("num1的类型是%T,num1的值为%v", num1, num1) }
函数的返回值可以支持命名,里面的顺序可以不一样
package main import "fmt" func test1(num1 int, num2 int) (sum int, sub int) { sub = num1 - num2 sum = num1 + num2 return sum, sub } func main() { var n1 = 10 var n2 = 5 var sum, sub = test1(n1, n2) fmt.Println(sum, sub) }
init函数
每一个源文件包含一个init函数,该函数会在main函数调用前,被go框架所执行
package main import "fmt" func init() { fmt.Println("init被执行") } func main() { fmt.Println("main被执行") } //init被执行 //main被执行
匿名函数
只希望被调用一次,可以使用到匿名函数,定义的同时被调用
package main import "fmt" // 让匿名函数在全局有效 var Mul = func(num1 int, num2 int) int { return num1 * num2 } func main() { //定义匿名函数 var res = func(num1 int, num2 int) int { return num1 + num2 }(10, 20) fmt.Println(res) //将匿名函数赋值给一个变量,这个变量实际上是函数类型的变量 //sub等价于匿名函数 sub := func(num1 int, num2 int) int { return num1 - num2 } //调用sub res01 := sub(50, 20) fmt.Println(res01) var res02 = Mul(2, 3) fmt.Println(res02) }
闭包
返回的匿名函数+匿名函数以外的变量 = 闭包
闭包的值会一直保存到内存中
package main import "fmt" // 闭包 func getSum() func(int) int { var n = 10 return func(i int) int { n = n + i return n } } func main() { f := getSum() fmt.Println(f(1))//11 fmt.Println(f(1))//12 }
defer 关键字
package main import "fmt" func main() { fmt.Println(add(30, 60)) } func add(num1 int, num2 int) int { //在Golang中程序遇到关键字defer不会立即执行,而是将defer后的语句压入栈中,继续执行函数后的语句 defer fmt.Println("num1=", num1) defer fmt.Println("num2=", num2) var sum = num1 + num2 fmt.Println("sum=", sum) return sum } /* 按照先进后出的规则 sum= 90 num2= 60 num1= 30 90 */
应用场景:想要关闭某些资源时,在前面加入defer关键字,因为defer有延迟机制
系统函数
package main import ( "fmt" "strconv" "strings" ) func main() { //1.统计字符串 var str = "golang你好" //Golang中汉字是utf-8字符集,一个汉字三个字节 fmt.Println(len(str)) //12 //2.对字符串进行遍历 方式一 //索引为0,值为g //索引为1,值为o //索引为2,值为l //索引为3,值为a //索引为4,值为n //索引为5,值为g //索引为6,值为你 //索引为9,值为好 for i, value := range str { fmt.Printf("索引为%d,值为%c \n", i, value) } //方式二利用切片 //'g''o''l''a''n''g''你''好' var r = []rune(str) for i := 0; i
package main import ( "fmt" "strings" ) func main() { //9.字符串替换 n=-1表示全部替换,替换两个n=2 var str = strings.Replace("golangandjava", "go", "golang", 2) fmt.Println(str) //10.切割 var str1 = strings.Split("go-java-c++", "-") fmt.Println(str1) //[go java c++] //11.大小写转化 strings.ToLower("A") strings.ToUpper("a") //12.去除空格 strings.TrimSpace(" goandjava ") //13.去除左右两边指定字符 strings.Trim("-javago-", "-") //14.判断字符是否是指定字符开头,结尾 strings.HasPrefix("http://123.123", "http") strings.HasSuffix("http://123.123", "123") }
日期函数
package main import ( "fmt" "time" ) func main() { //日期函数 var now = time.Now() //返回值的类型是一个结构体 fmt.Printf("类型是%T \n", now) //time.Time fmt.Println(now) //2024-06-13 14:25:35.9049279 +0800 CST m=+0.002579401 year := now.Year() month := now.Month() day := now.Day() fmt.Println(year, month, day) }
内置函数
不需要导包,直接使用
package main import "fmt" func main() { var str = "golang" fmt.Println(len(str)) //new函数分配内存,new函数的实参是一个类型而不是具体数值,返回值是对应类型的指针 var num = new(int) fmt.Printf("num的类型是%T,num的值为%v,num的地址为%v,num指向的值为%v", num, num, &num, *num) //num的类型是*int,num的值为0xc00000a0f8,num的地址为0xc000062030,num指向的值为0 }
错误处理机制
使用defer+recover管理错误
package main import "fmt" func main() { //利用defer+recover+匿名函数捕获异常 defer func() { var err = recover() if err != nil { fmt.Println("错误被捕获") fmt.Println("错误是", err) } }() var num1 = 10 var num2 = 0 var res = num1 / num2 fmt.Println(res) }
自定义错误
package main import ( "errors" "fmt" ) func main() { err := test() if err != nil { fmt.Println("自定义错误", err) } fmt.Println("正常执行下面逻辑") } func test() (err error) { num1 := 10 num2 := 0 if num2 == 0 { //抛出自定义异常 return errors.New("除数不能为0") } else { fmt.Println(num1 / num2) return nil } } //自定义错误 除数不能为0 //正常执行下面逻辑
数组
package main import "fmt" func main() { var num [3]int num[0] = 1 num[1] = 2 num[2] = 3 var sum int for i := 0; i
数组默认是值传递,想要在外部修改原有的值,需要传递地址
package main import ( "fmt" ) func main() { var arr = [...]int{1, 2, 3} fmt.Println("原数组的值为", arr) test(&arr) fmt.Println("修改后数组的值为", arr) //原数组的值为 [1 2 3] //修改后数组的值为 [4 2 3] } func test(arr *[3]int) { arr[0] = 4 }
二维数组
package main import "fmt" func main() { var arr = [2][3]int{{1, 2, 3}, {4, 5, 6}} fmt.Println(arr) }
切片
建立在数组上的一种抽象,构建在数组之上,并且提供了更强大的能力,
是对数组一个连续片段的引用,所以切片是一种引用类型,这个片段可以是整个数组
或者是由起始和终结标识符的一些项的子集
package main import "fmt" func main() { var arr = [6]int{1, 2, 3, 4, 5, 6} //切片构建在数组之上,左闭右开 var slice = arr[1:3] fmt.Println(slice) //切片的构建 var slice1 = make([]int, 4, 20) fmt.Println("slice1的长度", len(slice1)) fmt.Println("slice1的最大容量", cap(slice1)) var slice2 = []int{1, 2, 3} fmt.Printf("slice2的类型%T \n", slice2) fmt.Println("slice2的长度", len(slice2)) fmt.Println("slice2的最大容量", cap(slice2)) }
可以实现动态扩容,底层是创建一个新数组将老数组复制到新数组中
package main import "fmt" func main() { var slice2 = []int{1, 2, 3} var slice3 = append(slice2, 4, 5) fmt.Println(slice3)//1,2,3,4,5 }
映射
go中内置的数据类型,将键值进行关联,通过key获取val
package main import "fmt" func main() { //只声明是不会分配内存空间的 var a = make(map[int]string, 10) a[1] = "张三" a[2] = "李四" a[3] = "王五" fmt.Println(a) var b = make(map[int]string) b[1] = "张三" b[2] = "李四" fmt.Println(b) var c = map[int]string{ 1: "张三", 2: "李四", } fmt.Println(c) }
面向对象
package main import "fmt" type Person struct { Name string Age int } func main() { //方式一 var p1 = Person{ Name: "张三", Age: 18, } fmt.Println(p1) //方式二创建结构体的指针,应该给地址指向的字段赋值 var p2 *Person = new(Person) (*p2).Name = "李四" (*p2).Age = 20 fmt.Println(*p2) //方式三 var p3 = &Person{ "王五", 30, } fmt.Println(p3) }
package main import "fmt" type A struct { Num int } // 方法与结构体是绑定关系,如果其他类型调用test会报错,并且是值传递 func (a A) test() { fmt.Println(a.Num) } func main() { var p = A{ Num: 1, } p.test() } a[3] = "王五" fmt.Println(a) var b = make(map[int]string) b[1] = "张三" b[2] = "李四" fmt.Println(b) var c = map[int]string{ 1: "张三", 2: "李四", } fmt.Println(c) }
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。