商城站到汤泉池,智能制造,留下手机号预约看房,互联网公司排名咸阳一#xff1a;声明变量
在golang语言中声明变量的方式 package main import fmt func main() { var a int 3 //关键字 var 变量名 变量指定类型 变量值 var b int //关键字 var 变量名 变量指定类型(注意:当变量没赋值时是按照变量…一声明变量
在golang语言中声明变量的方式 package main import fmt func main() { var a int 3 //关键字 var 变量名 变量指定类型 变量值 var b int //关键字 var 变量名 变量指定类型(注意:当变量没赋值时是按照变量指定类型的默认值进行赋值如 【var b int】最后输出的就是int类型的0 而【var b bool】则会输出bool类型的false ) var c 4 //关键字 var 变量名 变量值(注意:当变量未设置类型则会根据变量值自行补充如【var c 4】则c的类型为int 而【var c hello】c的类型则为string) var d, e int 1, 2 //这是在第一个声明的基础上进行多个变量声明 var f, g int //这是在第二个声明基础上进行多个变量声明 var h, i 7, 8 //这是在第三个声明基础上进行多个变量声明 //输出 fmt.Println(a, b, c, d, e, f, g, h, i) //输出的值为 3 0 4 1 2 0 0 7 8 } 注意在方法中设置变量的时候一定要在方法体中用到否则会报错(如果 var c int 在方法中却没有使用则运行程序会报错!) -- go的全局变量不限制仅校验方法中的变量
go中除了用 var 关键字声明的变量外还提供了 : 的方式声明未声明过的变量。 package main import fmt func main() { a : 3 b : hellow c, d : 8, word //输出 fmt.Println(a, b, c, d) //输出的值为 3 hellow 8 word } 注意: 只能用于声明 未被声明过的变量( 如声明 var a int 3 后再 a : 4 就会报错)
二声明常量
常量的声明可以参考变量声明的第一部分-此处省略
const a int 3 //关键字 const 常量名 常量类型 常量值
注意常量在方法中声明不校验是否调用、
除了上面的常量声明方式外常量还可用作枚举 package mainimport fmtfunc main() {const (Unknown 0Female 1Male 2)//输出fmt.Println(Unknown, Female, Male)//输出值为 0 1 2
} 在常量声明时可以引入“unsafe” 包使用 函数计算表达式注意:必须是系统内置函数 package main import fmt import unsafe func main() { const ( a abc b len(a) c unsafe.Sizeof(a) ) const e string abg const f int len(a) const g unsafe.Sizeof(a) //输出 fmt.Println(a, b, c, e, f, g) //输出值为 abc 3 16 abg 3 16 } 相对于常量声明中 枚举类型 有个 iota 用法 就是 从0开始依次递增 package main import fmt func main() { const ( a iota //0 b //1 c //2 d ha //独立值iota 1 e //ha iota 1 f 100 //iota 1 g //100 iota 1 h iota //7,恢复计数 i //8 ) fmt.Println(a,b,c,d,e,f,g,h,i) } 三、运算符
go的运算符和其他编程语言基本一致
(加)、-(减)、*(乘)、/(除)、%(取余数)、(自增)、--(自减)、(相等)、!(不等)、(大于)、(小于)、(大于等于)、(小于等于)、(与)、||(或)、!(非)等等
这里着重记录一下 位运算 和 其他运算符 (了解即可日常业务中很少用到)
位运算符(二进制相与)、|(二进制相或)、^(二进制相异)、(二进制左移)、(二进制右移) package main import fmt func main() { var a uint 60 /* 60 0011 1100 */ var b uint 13 /* 13 0000 1101 */ var c uint 0 c a b /* 12 0000 1100 */ //二进制相与当二进制码对应位都为1时记录为1 fmt.Printf(第一行 - c 的值为 %d\n, c ) c a | b /* 61 0011 1101 */ //二进制相或当二进制码对应位有一位为1时记录为1 fmt.Printf(第二行 - c 的值为 %d\n, c ) c a ^ b /* 49 0011 0001 */ //二进制相异当二进制码对应位值不同时记录为1 fmt.Printf(第三行 - c 的值为 %d\n, c ) c a 2 /* 240 1111 0000 */ //二进制左移,将左侧丢弃右侧填补为02就是丢弃两位 fmt.Printf(第四行 - c 的值为 %d\n, c ) c a 2 /* 15 0000 1111 */ //二进制右移将右侧丢弃左侧填补为0 fmt.Printf(第五行 - c 的值为 %d\n, c ) } 其他运算符(获取变量存储地址)、*(指针变量) package main import fmt func main() { var a int 4 var ptr *int /* 和 * 运算符实例 */ ptr a /* ptr 包含了 a 变量的地址 */ fmt.Printf(a 的值为 %d\n, a); //输出a变量的值 4 fmt.Printf(a 的值为 %d\n, a); //输出a变量的变量存储地址能粗浅理解为数据库的索引 fmt.Printf(*ptr 为 %d\n, *ptr); //输出的是指针变量下的值 4 fmt.Printf(ptr 为 %d\n, ptr); //输出指针变量的存储地址 } 在go中也有其他语言的 if、if...else..、switch、等。
也有for 循环和嵌套有 break、continue、goto语句。
注意在go中没有while循环 四、函数、方法声明和调用 package main import fmt func main() { var a, b int 4,5 var c int var s string c sum(a,b) s fmt.Sprintf(获取ab%d,c) fmt.Println(s) } func sum(x int,y int) int{ //声明函数 关键字func 函数名称 函数参数和参数类型 返回类型 return xy } 注意声明函数的时候必须设定参数类型和返回值类型 这里记录一下 函数多个返回值 和 函数闭包(匿名函数) 的用法 package main import fmt func main() { a, b : swap(Google, Runoob) fmt.Println(a, b) } func swap(x, y string) (string, string) { //设定两个string类型的返回值 return y, x } package main import fmt func main() { // 定义一个匿名函数并将其赋值给变量add add : func(a, b int) int { return a b } // 调用匿名函数 result : add(3, 5) fmt.Println(3 5 , result) // 在函数内部使用匿名函数 multiply : func(x, y int) int { return x * y } product : multiply(4, 6) fmt.Println(4 * 6 , product) // 将匿名函数作为参数传递给其他函数 calculate : func(operation func(int, int) int, x, y int) int { return operation(x, y) } sum : calculate(add, 2, 8) fmt.Println(2 8 , sum) // 也可以直接在函数调用中定义匿名函数 difference : calculate(func(a, b int) int { return a - b }, 10, 4) fmt.Println(10 - 4 , difference) } 再记录一下 go 中的方法 package main import ( fmt ) /* 定义结构体 */ type Circle struct { radius float64 } func main() { var c1 Circle c1.radius 10.00 fmt.Println(圆的面积 , c1.getArea()) } //该 method 属于 Circle 类型对象中的方法 func (c Circle) getArea() float64 { //c.radius 即为 Circle 类型对象中的属性 return 3.14 * c.radius * c.radius } 注意从上面的例子中我们可以看出在go中 方法和函数是不同的。方法在定义的时候会在 func 关键字后面 方法名的前面 设置一个接收器( c Circle) 该接收器可在方法中调用
五、变量作用域
函数方法外面的是全局变量方法或函数内的则是局部变量局部变量优先级大于全局变量。局部变量除非作为参数传入另一个方法或函数中否则两个方法或函数中的局部变量不能共用。
六、数组
在go中初始化数组需要明确个数和类型 var a [10]int //初始化数组 关键字 var 数组名 [数组元素个数]数组元素类型 var a [5]int{1,2,3,4,5} //初始化数组 a 并赋值 a : [5]int{1,2,3,4,5} //省略关键字 var 初始化数组 a 并赋值 var a [...]int{1,2,3} //省略数组元素个数通过...程序会自动通过赋值确定元素个数 a : [...]int{1,2,3} //和上面同理 var a []int //设置空切片a 注意不指定长度的数组都是切片第七点记录切片 a : []int{} //设置空切片a 多维数组也同理 var a [][]int 初始化即可 package main import fmt func main() { // Step 1: 创建数组 values : [][]int{} //创建二维空数组 // Step 2: 使用 append() 函数向空的二维数组添加两行一维数组 row1 : []int{1, 2, 3} row2 : []int{4, 5, 6} values append(values, row1) values append(values, row2) // Step 3: 显示两行数据 fmt.Println(Row 1) fmt.Println(values[0]) fmt.Println(Row 2) fmt.Println(values[1]) // Step 4: 访问第一个元素 fmt.Println(第一个元素为) fmt.Println(values[0][0]) } 七、切片
相较于数组的长度不可改变go还提供了切片的类型也可以称之为 动态数组即它的长度不固定可以直接追加元素提升切片的元素数 通过make()函数来创建切片 var slice []type make([]type, len) //注意len只是定义切片的初始长度 可以为0 slice : make([]type, len) 如 slice1 : make([]int,0) //这行代码创建了个长度为0 的slice1 切片 除了用make() 函数来创建切片外 slice2 : []int{} 和 var slice2 []int 也是初始化了一个切片 对于数组来说切片除了不用固定长度这一个优点外还有一个切片赋值的功能 package main import fmt func main() { arr :[]int {1,2,3 } //初始化一个切片 a 里面有三个值 s : arr[0:2] //将切片下标0-2 的值 赋值给s fmt.Println(s) //输出 [1 2] fmt.Println(len(arr)) // fmt.Println(cap(arr)) // } 切片除了通过[:]来获取指定下标的值由于切片有索引所以go很多内置函数都可作用于切片上
如len()//获取切片长度 cap() //计算容量获得切片最大长度
八、range的用法
当需要循环数组、切片、集合等数据时可以用for range 的关键字来遍历。 package main import fmt var pow []int{1, 2, 4, 8, 16, 32, 64, 128} func main() { for i, v : range pow { //应用range时会直接将循环中的key值提供给ivalue值提供给v(i,v是变量类型可以设置成你熟悉的变量名 如k,v 也可以) fmt.Printf(2**%d %d\n, i, v) } } 除了将 pow 的值完全按照 key-value 的形式完全赋值给 i,v 外如果只想要key则可以省略v 如for i : range pow{ 或者用 _ 代替 如 for i,_ : range pow {
当然如果只想要value 不要key时也可以用 _ 代替 如: for _,v : range pow{
注意//range也可以用来枚举 字符串。第一个参数是字符的索引第二个是字符Unicode的值本身 九、map的用法
Map 是一种集合所以我们可以像迭代数组和切片那样迭代它。不过Map 是无序的遍历 Map 时返回的键值对的顺序是不确定的。
在获取 Map 的值时如果键不存在返回该类型的零值例如 int 类型的零值是 0string 类型的零值是 。
Map 是引用类型如果将一个 Map 传递给一个函数或赋值给另一个变量它们都指向同一个底层数据结构因此对 Map 的修改会影响到所有引用它的变量。 // 创建一个空的 Map m : make(map[string]int) // 创建一个初始容量为 10 的 Map m : make(map[string]int, 10) // 使用字面量创建 Map
m : map[string]int{apple: 1,banana: 2,orange: 3,
} // 获取键值对
v1 : m[apple] //map 就和 php中的数组对象类似用值的时候直接 变量[key值] 即可
v2, ok : m[pear] // 如果键不存在ok 的值为 falsev2 的值为该类型的零值 Map很像php 中的数组对象类型但是Map是引用类型要注意改变其中一个值时 其他引用过Map的变量都会更改 package main import fmt func main() { s : map[string]string{ //初始化一个map数据 one : one, two : two, three : three, } c : s //将 s 赋值给 c a : s[two] b : s[two] a for fmt.Println(a, b, s, c) //输出值 for two map[one:one three:three two:two] map[one:one three:three two:two] s[two] fiv fmt.Println(a, b, s, c) //for two map[one:one three:three two:fiv] map[one:one three:three two:fiv] } 从上面的示例可以看出当将整个map类型的s赋值给c时修改s 的值c同样会变化
delete() 函数可以删除map中的值 delete(map变量,需要删除的key值)
十、变量类型转换
1、数值类型转换 var a float64 3.7415926 //定义float64类型a为3.7415926 var b int int(a) //将a转变成int类型赋值给b fmt.Println(a, b) //输出结果 a3.7415926 b3 从float转化为int时会直接舍去小数点后的值 注意go 不支持隐式转换类型比如 : package main
import fmtfunc main() { var a int64 3var b int32b afmt.Printf(b 为 : %d, b)
}会报错 cannot use a (type int64) as type int32 in assignment
cannot use b (type int32) as type string in argument to fmt.Printf 但是如果改成 b int32(a) 就不会报错了: package main
import fmtfunc main() { var a int64 3var b int32b int32(a)fmt.Printf(b 为 : %d, b)
}2、字符串类型转换 var str string 10 //定义字符串str
var num int //初始化int类型num
num, _ strconv.Atoi(str) //将字符串转换为num的数据类型其中 _ 位置取的是转换时的错误信息如果想查看错误信息则需var msg error //定义error类型 msg num,msg strconv.Atoi(str) //通过 msg 获取转换失败的信息 或者可以用下面方法直接获取 number, msg strconv.Atoi(str) //没有错误时 msg为nil 注意使用strconv.Atoi() 函数时要引入 strconv 包
3.接口类型转换
接口类型转换有两种情况类型断言和类型转换。
类型断言用于将接口类型转换为指定类型 value.(T) 其中 value 是接口类型的变量 T 是要转换成的类型。
如果类型断言成功它将返回转换后的值和一个布尔值这个布尔值表示转换是否成功。 package main import fmt func main() { var i interface{} Hello, World //定义接口变量i str, ok : i.(string) //将i类型断言为字符串类型 返回转换后的值和断言结果 if ok { //类型断言成功 fmt.Printf(%s is a string\n, str) } else { //类型断言失败 fmt.Println(conversion failed) } } 类型转换用于将一个接口类型的值转换为另一个接口类型 T(value) T 是目标接口类型value 是要转换的值。
注意在类型转换中我们必须保证要转换的值和目标接口类型之间是兼容的否则编译器会报错。 package main import fmt type Write interface { //定义接口Write 接口参数为 []byte类型数据 返回值为 int 和 error类型 Write([]byte)(int,error) } type WriteString struct { //定义结构体WriteString 结构体属性 str 为字符串类型 str string } func (ws WriteString) Write(data []byte)(int, error){ ws.str string(data) return len(ws.str) , nil } func main(){ var w WriteString ss : hellow_Word! sb : []byte(ss) fmt.Println(w.Write(sb)) } 十一、go实现并发
Go 允许使用 go 语句开启一个新的运行期线程 即 goroutine以一个不同的、新创建的 goroutine 来执行一个函数。 同一个程序中的所有 goroutine 共享同一个地址空间。 package main import ( fmt time ) func say(s string) { for i : 0; i 5; i { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main() { go say(world) say(hello) } //输出的 world 和 hello 出现的顺序并不固定也从侧面证明了 使用go关键字后确实 两次方法调用确实没有先后是处于两条并发线程中 通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 - 用于指定通道的方向发送或接收。如果未指定方向则为双向通道。 package main import fmt func sum(s []int, c chan int) { sum : 0 for _, v : range s { sum v } c - sum // 把 sum 发送到通道 c } func main() { s : []int{7, 2, 8, -9, 4, 0} c : make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y : -c, -c // 从通道 c 中接收 fmt.Println(x, y, xy) } 目前我认为通道的作用 就是用于等待时常 可以同时获取到 两个goroutine 的值。
注意x和y的值不一定是按照执行代码先后时间来分配的也就是说x有可能获得第二个结果 如下面的代码只要多执行几次总会获得 *d, *e, *f 依旧会输出 1, 2, 3 的情况 或者 其中几个值是sum 运行后的值从而证明了 并发并不是执行完goroutine 之后再进行下面代码的执行。 package main import fmt func sum(s []int, c *int) { sum : 0 for _, v : range s { sum v } *c sum fmt.Println( sum中,*c,------\n) } func main() { s : []int{7, 2, 8, -9, 4, 0} a,b,c : 1,2,3 d, e, f : a, b, c go sum(s[:len(s)/2], d) go sum(s[len(s)/2:], e) go sum(s[2:len(s)-2], f) fmt.Println( 变量值 ,*d, *e, *f,------\n) } 或者我提供另一个佐证 执行这段代码时会沉睡直至x和y 接收到结果 package main import ( fmt time ) func sum(s []int, c chan int) { sum : 0 time.Sleep(10 * time.Second) //沉睡十秒 for _, v : range s { sum v } c - sum // 把 sum 发送到通道 c } func main() { s : []int{7, 2, 8, -9, 4, 0} c : make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y : -c, -c // 从通道 c 中接收 fmt.Println(x, y, xy) } 学习时借助查看 菜鸟教程
网址Go 语言教程 | 菜鸟教程