变量的数据类型
整数数据类型
- 有符号类型 int8 int16 int32 int64
- 无符号类型 uint8 uint16 uint32 uint64
浮点数据类型
- float32 4字节
- float64 8字节
布尔型
go
package main
import (
"fmt"
)
func main() {
var s = true
fmt.Println(s)
}
字符串
不可变:指的是字符串一旦定义好,其中字符的值不可以改变,如果输入特殊字符,字符串形式为反引号
go
package main
func main() {
var s1 = `
var s = true
println(s)`
println(s1)
}
可以保留原有的输入的内容
类型转化
只能进行强类型转化,不支持自动类型转化,原有的类型不变,只是将数值转化
go
package main
func main() {
var a = 101
var b = string(a)
println(b)
}
注意:int64转化为int8时编译不会出错,但是数值会溢出
其他类型转化为String
使用Sprintf函数进行转化
go
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函数进行转化
go
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类型转化为其他类型
go
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)
}
指针
go
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
*/
注意点
- 指针可以改变具体的值
- 指针变量接受的是地址
- 指针的地址不可以不匹配
流程控制语句
go
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 < 10; i++ {
fmt.Printf("%v \n", i)
}
//for range遍历:每个结果的索引被i接收,每个结果被val接收,遍历是对字符遍历
var str = "hello,go语言"
for i, val := range str {
fmt.Printf("i=%v,val=%q \n", i, val)
}
/* 输出为:
i=0,val='h'
i=1,val='e'
i=2,val='l'
i=3,val='l'
i=4,val='o'
i=5,val=','
i=8,val='g'
i=9,val='o'
i=10,val='语'
i=13,val='言'
*/
}
goto用法
go
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)
}
函数
go
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)
通过地址交换两个数
go
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函数可以作为一个数据类型,赋值给一个变量
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)
}
自定义数据类型
go
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)
}
函数的返回值可以支持命名,里面的顺序可以不一样
go
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框架所执行
go
package main
import "fmt"
func init() {
fmt.Println("init被执行")
}
func main() {
fmt.Println("main被执行")
}
//init被执行
//main被执行
匿名函数
只希望被调用一次,可以使用到匿名函数,定义的同时被调用
go
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)
}
闭包
返回的匿名函数+匿名函数以外的变量 = 闭包
闭包的值会一直保存到内存中
go
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 关键字
go
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有延迟机制
系统函数
go
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 < len(r); i++ {
fmt.Printf("%q", r[i])
}
println()
//3.字符串转化整数
n, _ := strconv.Atoi("66")
fmt.Println(n)
//4.整数转为字符串
var str1 = strconv.Itoa(10)
fmt.Println(str1)
//5.统计一个字符串有多少指定的子串
var count = strings.Count("javaandgolang", "a")
fmt.Println(count) //4
//6.不区分大小写的字符串的比较
fmt.Println(strings.EqualFold("go", "GO")) //true
//7.查看子串是否在字符串内
var res = strings.Contains("golang", "o")
println(res)
//8.返回一个子串在字符串中第一次出现的索引,没有就返回-1
var index = strings.Index("golang", "a")
fmt.Println(index) //3
}
go
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")
}
日期函数
go
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)
}
内置函数
不需要导包,直接使用
go
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管理错误
go
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)
}
自定义错误
go
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
//正常执行下面逻辑
数组
go
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 < len(num); i++ {
sum += num[i]
}
fmt.Println(sum)
//初始化数组
var arr [3]int = [3]int{10, 11, 12}
fmt.Println(arr)
var arr2 = [...]int{1, 2, 3, 4}
fmt.Println(arr2)
var arr3 = [...]int{1: 10, 2: 1, 0: 5}
fmt.Println(arr3)
}
数组默认是值传递,想要在外部修改原有的值,需要传递地址
go
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
}
二维数组
go
package main
import "fmt"
func main() {
var arr = [2][3]int{{1, 2, 3}, {4, 5, 6}}
fmt.Println(arr)
}
切片
建立在数组上的一种抽象,构建在数组之上,并且提供了更强大的能力,
是对数组一个连续片段的引用,所以切片是一种引用类型,这个片段可以是整个数组
或者是由起始和终结标识符的一些项的子集
go
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))
}
可以实现动态扩容,底层是创建一个新数组将老数组复制到新数组中
go
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
go
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)
}
面向对象
go
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)
}
go
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)
}