|
| 1 | +### 好记性不如烂笔头 |
| 2 | +青岛不倒我不倒,雪花不飘我不飘,不要问我多少量,手指大海方向,只要姑娘长的好,一杯雪碧我就倒 |
| 3 | + |
| 4 | +### 常量-声明和限制 |
| 5 | +在Go的常量定义中,使⽤ const 关键字,并且不能使⽤ := 标识符。 |
| 6 | +常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串 |
| 7 | +### 变量的声明方法 |
| 8 | +var identifier type |
| 9 | +var a int |
| 10 | +var b = "douyin" |
| 11 | +a := 9, 10 |
| 12 | +### 基础数据类型 |
| 13 | +go是⼀种强类型语⾔,也就是说⼀旦⼀个变量被指定了某个数据类型,如果不经过强制转化,那 |
| 14 | +么它就永远是这个数据类型了。⽐如⼀开始声明变量str的类型是字符串,接着⼜赋给变量str⼀个 |
| 15 | +int类型的值,这是不允许的。这时候我们就需要通过类型转化,go中没有隐式类型,只能通过下 |
| 16 | +⾯的强类型转换⽅式。 |
| 17 | +valueOfTypeB = typeB(valueOfTypeA) // 同类 |
| 18 | + |
| 19 | +只有相同底层类型的变量之间可以进⾏相互转换(如将 int16 类型转换成 int32 类型) |
| 20 | + |
| 21 | +int 和unit可以转换吗 |
| 22 | +正数int和unit转换没问题,负数转化成unit因为符号增加一位数 |
| 23 | +``` |
| 24 | +package main |
| 25 | +
|
| 26 | +import "fmt" |
| 27 | +
|
| 28 | +func main() { |
| 29 | + var a int8 |
| 30 | + a = -123 |
| 31 | + println(uint8(a)) |
| 32 | + /* |
| 33 | + PS F:\workspace\Leetcode> go run .\main.go |
| 34 | + 133 |
| 35 | + */ |
| 36 | + var b int8 |
| 37 | + b = 123 |
| 38 | + println(uint8(b)) |
| 39 | + /* |
| 40 | + PS F:\workspace\Leetcode> go run .\main.go |
| 41 | + 123 |
| 42 | + */ |
| 43 | + // var s string |
| 44 | + // s = "123" |
| 45 | + // println(int(s)) |
| 46 | + /* |
| 47 | + # command-line-arguments |
| 48 | + .\main.go:22:13: cannot convert s (type string) to type int |
| 49 | + */ |
| 50 | + fmt.Print(string(b)) |
| 51 | + /* |
| 52 | + PS F:\workspace\Leetcode> go run .\main.go |
| 53 | + 133 |
| 54 | + 123 |
| 55 | + { |
| 56 | + */ |
| 57 | +} |
| 58 | +
|
| 59 | +``` |
| 60 | +概念 |
| 61 | + |
| 62 | +原码表示法规定:用符号位和数值表示带符号数,正数的符号位用“0”表示,负数的符号位用“1”表示,数值部分用二进制形式表示。 |
| 63 | +反码表示法规定:正数的反码与原码相同,负数的反码为对该数的原码除符号位外各位取反。 |
| 64 | +补码表示法规定:正数的补码与原码相同,负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1. |
| 65 | +正零和负零的补码相同,[+0]补=[-0]补=0000 0000B |
| 66 | +我们来看整数-1在计算机中如何表示。 |
| 67 | + |
| 68 | +假设这也是一个int类型,那么: |
| 69 | +1、先取-1的原码:10000000 00000000 00000000 00000001 |
| 70 | +2、得反码: 11111111 11111111 11111111 11111110(除符号位按位取反) |
| 71 | +3、得补码:11111111 11111111 11111111 11111111 |
| 72 | +可见,-1在计算机里用二进制表达就是全1。16进制为:0xFFFFFF |
| 73 | +———————————————— |
| 74 | +版权声明:本文为CSDN博主「storm_fury」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 |
| 75 | +原文链接:https://blog.csdn.net/weixin_43215250/article/details/84193451 |
| 76 | + |
| 77 | +问题:-1的在计算机读取的时候不是读的0xFFFFFF么,那一个正数16777215的二进制值也是0xFFFFFF;;他俩在计算机存储的时候是一样的吗 |
| 78 | + |
| 79 | +### New 和 Make |
| 80 | +new 和 make 是go内建的两个函数,是⽤来创建并分配变量的内存地址。它们的区别在于new |
| 81 | +⼀般是给基本数据类型申请内存,⼀般很少⽤。make是给slice、map和channel申请内存,它返 |
| 82 | +回的是对应的这三个类型本身。 |
| 83 | + |
| 84 | +常用make |
| 85 | +- slice定义 |
| 86 | + - var identifier []type |
| 87 | + - var slice1 []type = make([]type, len) 也可以简写为 slice1 := make([]type, len) |
| 88 | + - 切片初始化 s :=[] int {1,2,3 } |
| 89 | + - 通过arr数组对切片初始化 s := arr[:] ;s := arr[startIndex:endIndex] ;s := arr[startIndex:] ;s := arr[:endIndex] |
| 90 | + |
| 91 | +切片是可索引的,并且可以由 len() 方法获取长度。 |
| 92 | + |
| 93 | +切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。 |
| 94 | + |
| 95 | +``` |
| 96 | +package main |
| 97 | +
|
| 98 | +import "fmt" |
| 99 | +
|
| 100 | +func main() { |
| 101 | + var numbers = make([]int,3,5) |
| 102 | +
|
| 103 | + printSlice(numbers) |
| 104 | +} |
| 105 | +
|
| 106 | +func printSlice(x []int){ |
| 107 | + fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +一个切片在未初始化之前默认为 nil,长度为 0, |
| 112 | +``` |
| 113 | +func main() { |
| 114 | + var a []int |
| 115 | + fmt.Printf("a=%t", a == nil) |
| 116 | + /* |
| 117 | + a=true |
| 118 | + */ |
| 119 | +} |
| 120 | +``` |
| 121 | + |
| 122 | +### 匿名函数 |
| 123 | +匿名函数(匿名函数因为没有函数名,所以没办法像普通函数那样调⽤,所以匿名函数需要保存到某个变量或者作为⽴即执⾏函数) |
| 124 | +``` |
| 125 | +console := bufio.NewReader(os.Stdin) |
| 126 | + readLine := func() (str string) { |
| 127 | + str, _ = console.ReadString('\n') |
| 128 | + return |
| 129 | + } |
| 130 | +``` |
| 131 | +### Defer |
| 132 | +defer 每操作一个函数,函数都会按照先进后出,后进先出的顺序进行运行 |
| 133 | + |
| 134 | +defer 表示延时推迟的意思,在go语⾔中⽤来延时⼀个函数或者⽅法的执⾏。如果⼀个函数或者 |
| 135 | +⽅法添加了defer关键字,表示则暂时不执⾏,等到主函数的所有⽅法都执⾏完后才开始执⾏。 |
| 136 | +当多个函数被defer的时候他们被添加到⼀个堆栈中,并且根据先进后出的原则执⾏。 即 Last |
| 137 | +In First Out(LIFO) |
| 138 | +由于 defer 语句延迟调⽤的特性,所以 defer 语句能⾮常⽅便的处理资源释放问题。⽐如:资 |
| 139 | +源清理、⽂件关闭、解锁及记录时间等。 |
| 140 | + |
| 141 | +在Go语⾔的函数中 return 语句在底层并不是原⼦操作,它分为给返回值赋值和RET指令两步。 |
| 142 | +⽽ defer 语句执⾏的时机就在返回值赋值操作后,RET指令执⾏前 |
| 143 | + |
| 144 | +``` |
| 145 | +func test() { |
| 146 | + println("testing") |
| 147 | +} |
| 148 | +func main() { |
| 149 | + var a []int |
| 150 | + fmt.Println(a == nil) |
| 151 | + defer test() |
| 152 | + return |
| 153 | + /* |
| 154 | + PS F:\workspace\Leetcode> go run .\main.go |
| 155 | + true |
| 156 | + testing |
| 157 | + */ |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +### 函数值传递-传递时会改变参数的地址/指针不改变 |
| 162 | +单传的传参是不改变指针地址的 |
| 163 | +``` |
| 164 | +func main() { |
| 165 | + var a int |
| 166 | + a = 1 |
| 167 | + println(a) |
| 168 | + ip := &a |
| 169 | + println(ip) |
| 170 | + print(fmt.Sprintln("初始%p", &ip)) |
| 171 | + change(ip) |
| 172 | + println(ip) |
| 173 | + print(fmt.Sprintln("改变后%p", &ip)) |
| 174 | +} |
| 175 | +func change(x *int) { |
| 176 | + print(fmt.Sprintln("传参%p", x)) |
| 177 | + *x = 1 |
| 178 | +} |
| 179 | +
|
| 180 | +/* |
| 181 | +1 |
| 182 | +0xc0000120b0 |
| 183 | +初始%p 0xc000006028 |
| 184 | +传参%p 0xc0000120b0 |
| 185 | +0xc0000120b0 |
| 186 | +改变后%p 0xc000006028 |
| 187 | +*/ |
| 188 | +
|
| 189 | +``` |
| 190 | +### 函数值传递-引用与改变 |
| 191 | +虽然go函数是值传递,但是传递的参数本身是值还是引⽤,和数据的特点以及类型有关系。这是 |
| 192 | +两个概念。 |
| 193 | +上⾯介绍了golang的数据类型分为基本类型和复合类型,按照数据特点划分 |
| 194 | +值类型: int、float、string、bool、array、struct 。值传递是传递的数值本身, |
| 195 | +不是内存地址。是将数据本身拷⻉⼀份传给函数,本身不受影响。 |
| 196 | +引⽤类型: slice、pointer、map、chan 等都是引⽤类型。因为存储的是内存地址,所以 |
| 197 | +传递的时候是传递了内存地址。 |
| 198 | + |
| 199 | + |
| 200 | +int、float、string、bool、array、struct 举例 |
| 201 | +``` |
| 202 | +func main() { |
| 203 | + var a int |
| 204 | + a = 1 |
| 205 | + change(a) |
| 206 | + print(a) |
| 207 | +} |
| 208 | +func change(x int) { |
| 209 | + x = 2 |
| 210 | +} |
| 211 | +
|
| 212 | +/* |
| 213 | +PS F:\workspace\Leetcode> go run .\main.go |
| 214 | +1 |
| 215 | +*/ |
| 216 | +
|
| 217 | +func main() { |
| 218 | + var a float32 |
| 219 | + a = 1 |
| 220 | + println(a) |
| 221 | + change(a) |
| 222 | + print(a) |
| 223 | +} |
| 224 | +func change(x float32) { |
| 225 | + x = 2 |
| 226 | +} |
| 227 | +
|
| 228 | +/* |
| 229 | +PS F:\workspace\Leetcode> go run .\main.go |
| 230 | ++1.000000e+000 |
| 231 | ++1.000000e+000 |
| 232 | +*/ |
| 233 | +。。。 |
| 234 | +``` |
| 235 | + |
| 236 | +slice、pointer、map、chan 改变是指其子元素的指向的地址改变了 |
| 237 | +``` |
| 238 | +import "fmt" |
| 239 | +
|
| 240 | +func main() { |
| 241 | + a := []int{1, 2} |
| 242 | + fmt.Printf("%+v", a) |
| 243 | + change(a) |
| 244 | + fmt.Printf("%+v", a) |
| 245 | +} |
| 246 | +func change(x []int) { |
| 247 | + x[0] = 22 |
| 248 | +} |
| 249 | +
|
| 250 | +/* |
| 251 | +PS F:\workspace\Leetcode> go run .\main.go |
| 252 | +[1 2][22 2] |
| 253 | +*/ |
| 254 | +``` |
| 255 | +其实本身的地址没改变-这和python可变/不可变对象其实很像了 |
| 256 | +``` |
| 257 | +func main() { |
| 258 | + a := []int{1, 2} |
| 259 | + println(&a) |
| 260 | + fmt.Printf("%+v", a) |
| 261 | + change(a) |
| 262 | + println(&a) |
| 263 | + fmt.Printf("%+v", a) |
| 264 | +} |
| 265 | +func change(x []int) { |
| 266 | + x[0] = 22 |
| 267 | +} |
| 268 | +``` |
0 commit comments