一.变量常量
1.变量定义
package main
import "fmt"
// 声明文件所在包 每个go文件必须有归属包
// go build test.go 编译 -o hello.exe 指定编译后文件名
// go run test.go 编译执行
// gofmt -w test.go 格式话操作
/*
源文件以 go 为扩展名
程序的执行入口是main()函数
严格区分大小写
方法由一条条语句构成 每个语句后不需要分号(go语言会在每行后自动加分号)
go编译器是一行行进行编译的,因此我们一行就写一条语句
定义的变量或者import的包如果没有使用到,代码不能编译通过
大括号都是成对出现的
*/
// 全家变量定义 可以一次性声明
var a1 = 100
var a2 = 0.01
var (
a3 = 500
a4 = "xxx"
)
func main() {
fmt.Println("He"+"llo", "Hello") // Hello Hello
var age1 int // 变量声明方式1 指定类型 赋值 var age int = 20
age1 = 19
var age2 int // 变量声明方式2 指定类型 不赋值 默认值
var age3 = 21 // 变量声明方式3 没有写变量类型 自动类型推断
age4 := 22 // 变量声明方式4 省略var 用:=
fmt.Println("age = ", age1, age2, age3, age4)
//支持多变量声明
var n1, n2, n3 int
fmt.Println(n1, n2, n3)
var n4, n5, n6 = "10", 0.1, 10
fmt.Println(n4, n5, n6)
fmt.Println(a1, a2, a3, a4)
}
Go 中的 全局变量比较特殊,如果全局变量首字母小写,则只能别当前包中的go文件使用,外部无法使用;
如果首字母大写,则任意文件都可以使用全局变量
2.匿名变量_
不占用命名空间,不会分配内存,所以匿名变量之间不存在重复声明
package main
func getUserinfo() (string, int) {
return "zhang", 19
}
func main() {
var username, _ = getUserinfo() // _ 匿名变量
println(username) // zhang
}
3.常量const
常量值无法改变
func main() {
const pi = 3.14 // 定义常量
fmt.Println(pi)
const ( // 定义多个常量
A = "A"
B = "B"
C // 省略值表示和上一行值相同
)
// const a, b, c = 1, 2, 3 // 定义多个常量
fmt.Println(A, B, C) // A B B
}
iota常量计数器
package main
import "fmt"
func main() {
const (
n1 = iota // 第一个值是iota,后面值累加
n2
_ // 跳过
n3
)
fmt.Println(n1, n2, n3) // 0 1 3
}
多iota定义一行
package main
import "fmt"
func main() {
const (
n1, c1 = iota + 1, iota + 2
n2, c2
n3, c3
)
fmt.Println(n1, n2, n3) // 1 2 3
fmt.Println(c1, c2, c3) // 2 3 4
}
二.基本数据类型
1.整数类型
类型 | 有无符号 | 占用存储空间 | 表数范围 |
---|---|---|---|
int8 | 有 | 1字节 | -128 ~ 127 |
int16 | 有 | 2字节 | -32768 ~ 32767 |
int32 | 有 | 4字节 | -2^31 ~ 2^31-1 |
int64 | 有 | 8字节 | -2^63 ~ 2^63-1 -2147483648~2147483647 |
uint8 | 无 | 1字节 | 0 ~ 255 |
uint16 | 无 | 2字节 | 0 ~ 65535 |
uint32 | 无 | 4字节 | 0 ~ 2^31-1 0~4294967295 |
uint64 | 无 | 8字节 | 0 ~ 2^63-1 |
类型 | |
---|---|
int | 在32位系统相对于int32,在64位系统相当于int64 |
uint | 在32位系统相对于uint32,在64位系统相当于uint64 |
runne | 等价于 int32 |
byte | 等价于 uint8 |
整数类型默认是int ,超出边界报错
package main
import "fmt"
var num = 28
func main() {
fmt.Printf("num类型是: %T", num) // num类型是: int
fmt.Println()
fmt.Println(unsafe.Sizeof(num)) // 变量占用字节数 8
}
类型转换
import "fmt"
var n1 int8 = 10
var n2 int16 = 20
func main() {
fmt.Println(int16(n1) + n2) // 把n1转换int16 进行计算
var n3 int64 = 888 // 将int64转为int8的时候,编译不会出错的,但是会数据的溢出
var n4 int8 = int8(n3)
fmt.Println(n4) //120
}
2.浮点型
类型 | 占用存储空间 | 表数范围 |
---|---|---|
float32 | 4字节 | -3.403E38~3.403E38 |
float64 | 8字节 | -1.798E308~1.798E308 |
浮点类型底层存储:符号位+指数位+尾数位,所以尾数位只是存了 一个大概,很可能会出现精度的损失。
float32的精度只能提供大约6个十进制数(表示后科学计数法后,小数点后6位)的精度
float64的精度能提供大约15个十进制数(表示后科学计数法后,小数点后15位)的精度
float64精度更高,通常使用float64,默认浮点类型是float64
var num = 3.14
fmt.Println(num)
package main
import "fmt"
func main() {
var num1 float32 = 3.14
fmt.Println(num1) // 3.14
var num2 float32 = -3.14
fmt.Println(num2) // -3.14
var num3 float32 = -314e-2 // e-2是科学计数法 10的-2次方
fmt.Println(num3) // -3.14
var num4 float32 = 314e+2 // e+2是科学计数法 10的2次方
fmt.Println(num4) // 31400
var num5 float32 = 1.000000916
fmt.Println(num5) // 1.000001
var num6 float64 = 1.000000916
fmt.Println(num6) // 1.000000916
}
格式化输出
package main
import "fmt"
func main() {
var n1 float32 = 3.1415926
fmt.Println(n1) // 3.1415925
fmt.Printf("%v %f %T\n", n1, n1, n1) // 3.1415925 3.141593 float32 %v 原样输出 %f默认保留六位小数点
fmt.Printf("%.2f\n", n1) // %.2f 输出数据的时候保留2位小数
}
float精度丢失
package main
import "fmt"
func main() {
var n1 float64 = 1129.6
fmt.Println(n1 * 100) // 112959.99999999999
m1, m2 := 8.2, 3.8
fmt.Println(m1 - m2) // 4.3999999999999995
}
decimal精度小数
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
func main(){
var num1 float64 = 3.1
var num2 float64 = 4.2
d1 := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2))
fmt.Println(d1)//7.3
}
3.布尔类型
布尔类型占1个字节,默认false
无法参与运算,也无法与其他类型转换
package main
import "fmt"
func main() {
var flag bool = 5 < 9
fmt.Println(flag)
}
4.字符串类型
默认为空 ""
转义字符
转义符 | 含义 | unicode值 |
---|---|---|
\b | 退格 | \u0008 |
\n | 换行 | \u000a |
\r | 回车 | \u000d |
\t | 制表符 tab | \u0009 |
\" | 双引号 | \u0022 |
' | 单引号 | \u0027 |
\ | 反斜杆 | \u005c |
package main
import "fmt"
func main() {
var s1 string = "这个\"字符串" // 字符串是不可变的:指的是字符串一旦定义好,其中的字符的值不能改变
var s2 = `这个"字符串` // 有特殊字符,可以用反引号 `,反引号还可以定义多行
s3 := "abc" + "ABC" // 字符串拼接 当一个字符串过长的时候:注意:+保留在上一行的最后
fmt.Println(s1, s2, s3) // 这个"字符串 这个"字符串 abcABC=
}
strconve函数基本数据类型转string
package main
import(
"fmt"
"strconv"
)
func main(){
var n1 int = 18
var s1 string = strconv.FormatInt(int64(n1),10) //参数:第一个参数必须转为int64类型 ,第二个参数指定字面值的进制形式为十进制
fmt.Printf("s1对应的类型是:%T ,s1 = %q \n",s1, s1)
var n2 float64 = 4.29
var s2 string = strconv.FormatFloat(n2,'f',9,64)
//第二个参数:'f'(-ddd.dddd) 第三个参数:9 保留小数点后面9位 第四个参数:表示这个小数是float64类型
fmt.Printf("s2对应的类型是:%T ,s2 = %q \n",s2, s2)
var n3 bool = true
var s3 string = strconv.FormatBool(n3)
fmt.Printf("s3对应的类型是:%T ,s3 = %q \n",s3, s3)
}
s1对应的类型是:string ,s1 = "18"
s2对应的类型是:string ,s2 = "4.290000000"
s3对应的类型是:string ,s3 = "true"
strconve函数string转基本数据类型
package main
import(
"fmt"
"strconv"
)
func main(){
//string-->bool
var s1 string = "true"
var b bool
//ParseBool这个函数的返回值有两个:(value bool, err error)
//value就是我们得到的布尔类型的数据,err出现的错误
//我们只关注得到的布尔类型的数据,err可以用_直接忽略
b , _ = strconv.ParseBool(s1)
fmt.Printf("b的类型是:%T,b=%v \n",b,b) // b的类型是:bool,b=true
//string---> int64
var s2 string = "19"
var num1 int64
num1,_ = strconv.ParseInt(s2,10,64) // 10 指定进制 int64
fmt.Printf("num1的类型是:%T,num1=%v \n",num1,num1) // num1的类型是:int64,num1=19
//string-->float32/float64
var s3 string = "3.14"
var f1 float64
f1,_ = strconv.ParseFloat(s3,64)
fmt.Printf("f1的类型是:%T,f1=%v \n",f1,f1) // f1的类型是:float64,f1=3.14
//注意:string向基本数据类型转换的时候,一定要确保string类型能够转成有效的数据类型,否则最后得到的结果就是按照对应类型的默认值输出
var s4 string = "golang"
var b1 bool
b1 , _ = strconv.ParseBool(s4)
fmt.Printf("b1的类型是:%T,b1=%v \n",b1,b1) // b1的类型是:bool,b1=false
var s5 string = "golang"
var num2 int64
num2,_ = strconv.ParseInt(s5,10,64)
fmt.Printf("num2的类型是:%T,num2=%v \n",num2,num2) // num2的类型是:int64,num2=0
}
字符串函数
// 1. len(str) 统计字符串长度,按字节统计
str := "golang你好" // 汉字是utf8字符集,一个汉字3个字节
fmt.Println(len(str)) // 12字节 不能用unsafe.Sizeof()
// 2. for range 字符串遍历
for i, value := range str { // 利用键值循环
fmt.Printf("索引 %d 值 %c \n",i, value)
}
索引 0 值 g
索引 1 值 o
索引 2 值 l
索引 3 值 a
索引 4 值 n
索引 5 值 g
索引 6 值 你
索引 9 值 好
// 3. strconv.Atoi()字符串转整数
num1,_ := strconv.Atoi("66")
fmt.Printf("%T \n",num1) // int
// 4. strconv.Itoa()整数转字符串
str1,_ := strconv.Itoa(66)
fmt.Printf("%T \n",str1)
// 5. strings.Contains()查找子串是否在指定的字符串中
package main
import "fmt"
import "strings"
func main(){
fmt.Println(strings.Contains("golang","go")) // true
}
// 6. strings.Count()统计一个字符串有几个指定的子串
fmt.Println(strings.Count("golang","go")) // 1
// 7. strings.EqualFold()不区分大小写的字符串比较
fmt.Println(strings.EqualFold("go" , "Go")) // true
// 8. strings.lndex()返回子串在字符串第一次出现的索引值,如果没有返回-1
fmt.Println(strings.Index("golang" , "an")) // 3
// 9. strings.Replace()字符串的替换 -1表示全部替换
fmt.Println(strings.Replace("golang", "g", "G", -1)) // GolanG
// 10. 按照指定的某个字符,为分割标识,将一个学符串拆分成字符串数组
fmt.Println(strings.Split("go-python-java", "-")) // [go python java]
// 11. 将字符串的字母进行大小写的转换
fmt.Println(strings.Split(strings.ToLower("Go")) // go
fmt.Println(strings.Split(strings.ToUpper"go")) //Go
// 12. strings.TrimSpace()将字符串左右两边的空格去掉
fmt.Println(strings.TrimSpace(" golang "))
// 13. strings.Trim()将字符串左右两边指定的字符去掉
fmt.Println(strings.Trim("~golang~ ", " ~"))
// 14. strings.TrimLeft()将字符串左边指定的字符去掉
fmt.Println(strings.TrimLeft("~golang~", "~")) // golang~
// 15. strings.TrimRight()将字符串右边指定的字符去掉
fmt.Println(strings.TrimRight("~golang~", "~")) // ~golang
// 16. strings.HasPrefix()判断字符串是否以指定的字符串开头
fmt.Println(strings.HasPrefix("golang", "go")) // true
// 17. strings.HasSuffix()判断字符串是否以指定的字符串结束
fmt.Println(strings.HasSuffix("golang", "ng")) // true
5.字符类型
Golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存。
Golang中字符使用UTF-8编码(Unicode是对应的字符集,UTF-8是Unicode的其中的一种编码方案)
package main
import "fmt"
func main() {
var n = '中'
fmt.Printf("%v,%T", n, n) // 20013,int32 码值 20013
}
三.复合数据类型
数组 切片 结构体 函数 map 通道(channel) 接口