package main
import "fmt"
func main() {
a := 0x20 //16进制
fmt.Println(a) //32
b := 0b100000 //二进制
fmt.Println(b) //32
var c = 32 //默认10进制
fmt.Println(c) //32
d := a + b + c
fmt.Printf("%T %d", d, d) //格式化输出%T打印的是类型:int 96
var e int64 = 100 //var e int64=int64(100)
fmt.Println(e)//int 32占4个字节,int 64占8个字节
}
一、math方法
方法 | 用途 | 备注 |
math.Ceil() | 向上取整 | |
math.Floor() | 向下取整 | |
math.Round() | 四舍五入 | |
math.Abs(-2.7) | 绝对值 | 结果:2.7 |
math.E math.Pi | 常量 | |
math.MaxInt16 math.MinInt16 | 极值 | Int16最大的数,Int16最小数 |
math.Log10(100) math.Log2(8) | 对数 | 结果:2 ,3 |
math.Max(1,3) math.Min(-2,3) | 最大值 最小值 | |
math.Pow(2,3) math.Pow10(3) | 幂 | , |
math.Mod(5,2) | 取模 | 5%2 |
math.Sqrt(9) | 开方 | 结果:3 |
二、输入
var a1, a2 string
n, err := fmt.Scan(&a1, &a2) //从控制台输入两个值
if err != nil { //err不为空
panic(err) //程序终止,不会向下执行
}
fmt.Println(n)
fmt.Printf("%T %[1]s,%T %[2]s", a1, a2)
"""
以下是控制台操作结果:
PS E:\projects> go run ./pro1/mian.go
aaa bbb
2
string aaa,string bbb
"""
三、切片与数组
1、切片
var a4=[...]int{1,3,5}//推断有几个元素
fmt.Println(len(a4),cap(a4),a4)
var a5=[5]int{1,5}//给前两个索引赋值
fmt.Println(a5)
var a6=[5]int{1:10,3:50}//定向赋值index:value index值不能超出索引范围
fmt.Println(a6)
a7:=[2][3]int{}//定义一个2行3列的数组
a7:=[2][3]int{1:{100,200,300}}
a7:=[...][3]int{4:{100,2:200,1:300}}//3不能用...代替,这是一个5行的数组
//数组的长度不可变,因此数组的len和cap一致
//go语言不支持负索引
for i,v:=range a6{
fmt.Println(i,v)
}
2、int数组地址排列
var a0 = [5]int{1, 3, 5, 7}
for i := 0; i < len(a0); i++ {
fmt.Printf("%p\t %d %d %p\n", &a0, i, a0[i], &a0[i])#int 8Bytes
}
a0[0] = 1000
fmt.Printf("%p\t %d %d %p\n", &a0, 0, a0[0], &a0[0])
"""
执行结果:
0xc000144030 0 1 0xc000144030
0xc000144030 1 3 0xc000144038
0xc000144030 2 5 0xc000144040
0xc000144030 3 7 0xc000144048
0xc000144030 4 0 0xc000144050
0xc0000103f0 0 1000 0xc0000103f0
"""
Int数组
- 数组必须在编译时就确定大小,之后不能改变
- 数组首地址就是数组地址
- 所有元素一个接一个顺序存储在内存中
- 元素的值可以改变,但是元素地址不变
3、string数组地址排列
var a1 = [...]string{"aab", "ccd", "a", "aaaaaabbbiiiuuuaaaxyz"}
for i := 0; i < len(a1); i++ {
fmt.Printf("%p\t %d %s %p\n", &a1, i, a1[i], &a1[i])
}
"""
执行结果:
0xc000028080 0 aab 0xc000028080
0xc000028080 1 ccd 0xc000028090
0xc000028080 2 a 0xc0000280a0
0xc000028080 3 aaaaaabbbiiiuuuaaaxyz 0xc0000280b0
"""
数组的地址存储在一个连续的内存中,地址指针指向堆中随意的地址。因此超出也不会影响数组的值
4、值赋值
func typ(arr [5]int) {
fmt.Printf("%p %d\n", &arr, arr)
}
func main() {
var a0 = [5]int{1, 3, 5, 7}
fmt.Printf("%p %d\n", &a0, a0)
var a1 = a0
fmt.Printf("%p %d\n", &a1, a1)
typ(a0)
}
"""
执行结果:
0xc0000103f0 [1 3 5 7 0]
0xc000010450 [1 3 5 7 0]
0xc0000104b0 [1 3 5 7 0]
地址不一致,说明这种赋值方式是重新创造了两个副本,属于值复制。
"""
5、make切片
切片:长度可变,容量可变
var a0 = [5]int{1, 3, 5, 7}
var a1 []int
fmt.Println(a0, len(a0), cap(a0))
fmt.Println(a1, len(a1), cap(a1))
var a2 = make([]int, 0, 0)#第一个参数是切片,第二个参数是长度,第三个参数是当前切片的容量
fmt.Println(a2, len(a2), cap(a2))
"""
执行结果:
[1 3 5 7 0] 5 5
[] 0 0
[] 0 0
"""
定义切片建议使用make,可以定义初始容量,减少频繁扩容
header标量值
- 指针:底层数组
- len:当前切片的元素个数
- cap:当前切片的容量
以下是切片的内存存储:
由于go中都是值复制的形式对变量进行赋值的,会导致数据垃圾比较多,为了解决扩容等问题因此引入切片。切片是长度可变,容量可变的。
var s0=s1这种方式对于切片来说只是复制了header标量值,因此解决了数组复制副本的问题。
s0 := make([]int, 3, 5)
s1 := append(s0, 7, 10)
fmt.Printf("%p\t %p %d\n", &s0, &s0[0], s0)
fmt.Printf("%p\t %p %d\n", &s1, &s1[0], s1)
"""
执行结果:
0xc000008078 0xc0000103f0 [0 0 0]
0xc000008090 0xc0000103f0 [0 0 0 7 10]
"""
如果长度超出数组的容量,则自动扩容。令开辟新的空间去创建一个数组,基址会改变。以上属于未超出容器长度,因此基址不变,只是复制了header而已。
go语言中全都是值传递,整型、数组这样类型的值是完全复制,slice、map、channel、interface、function这样的引用类型也是值拷贝,拷贝的是 标头值。