Go语言学习笔记(二)十分钟上手
加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959
变量&常量
变量
变量名由字母、数字、下划线组成,不能以数字开头。
- ...
- var (
- A int //默认为0
- B string //默认为""
- C bool //默认为false
- Name string = "suoning"
- Age = // 自动识别类型
- )
- func main() {
- sex := "man" //等价于 var sex string = "man"
- var girlfriend string //声明变量
- girlfriend = "Dawn" //变量赋值
- Name := "Nick" //正确
- //girlfriend := "Jenny" //错误的!不能申明两次
- ...
- }
常量
常量使用const 修饰,代表永远是只读的,不能修改。
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
语法:const identifier [type] = value,其中type可以省略。
iota
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。
- ...
- const (
- A = 'a' //
- B = iota //
- C //
- D = "nick" //"nick" iota += 1
- E //"nick" iota += 1
- F = //618 iota +=1
- G //618 iota +=1
- H = iota //
- I //
- )
- ...
基本数据类型
布尔型
布尔型的值只可以是常量 true 或者 false。
- var a bool
- var a bool = true
- var a = false
数字类型
int:
- uint8(无符号 8 位整型 (0 到 255))
- uint16(无符号 16 位整型 (0 到 65535))
- uint32(无符号 32 位整型 (0 到 4294967295))
- uint64(无符号 64 位整型 (0 到 18446744073709551615))
- int8(有符号 8 位整型 (-128 到 127))
- int16(有符号 16 位整型 (-32768 到 32767))
- int32(有符号 32 位整型 (-2147483648 到 2147483647))
- int64(有符号 64 位整型 (-9223372036854775808 到 9223372036854775807))
float:
- float32(IEEE-754 32位浮点型数)
- float64(IEEE-754 64位浮点型数)
- complex64(32 位实数和虚数)
- complex128(64 位实数和虚数)
其它:
- byte(类似 uint8)
- rune(类似 int32)
- uint(32 或 64 位)
- int(与 uint 一样大小)
- uintptr(无符号整型,用于存放一个指针)
类型转换
- package main
- func main() {
- var a int
- var b int32
- var c int64
- a =
- //b = a + a // compiler error
- b = int32(a + a) // ok
- b = b + // ok: 5 is a constant
- c = c + // ok
- }
字符类型
存储为ascii码
- var a byte = 'a'
- fmt.Println(a) //
字符串类型
字符串表示两种方式:
- 双引号
- `` (反引号,不转义)
string底层就是一个byte的数组
string本身是不可变的,因此要改变string中字符,需要如下操作:
- str := "hello world"
- s := []byte(str)
- s[] = 'o'
- str = string(s)
操作符
算术运算符
- + 相加
- - 相减
- * 相乘
- / 相除
- % 求余
- ++ 自增
- -- 自减
关系运算符
- == 检查两个值是否相等,如果相等返回 True 否则返回 False。
- != 检查两个值是否不相等,如果不相等返回 True 否则返回 False。
- > 检查左边值是否大于右边值,如果是返回 True 否则返回 False。
- < 检查左边值是否小于右边值,如果是返回 True 否则返回 False。
- >= 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。
- <= 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。
逻辑运算符
- && 逻辑 AND 运算符。 如果两边的操作数都是 True,则条件 True,否则为 False。
- || 逻辑 OR 运算符。 如果两边的操作数有一个 True,则条件 True,否则为 False。
- ! 逻辑 NOT 运算符。 如果条件为 True,则逻辑 NOT 条件 False,否则为 True。
位运算符
位运算符对整数在内存中的二进制位进行操作。
- & 按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。
- | 按位或运算符"|"是双目运算符。 其功能是参与运算的两数各对应的二进位相或。
- ^ 按位异或运算符"^"是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。
- << 左移运算符"<<"是双目运算符。左移n位就是乘以2的n次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。
- >> 右移运算符">>"是双目运算符。右移n位就是除以2的n次方。 其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。
赋值运算符
- = 简单的赋值运算符,将一个表达式的值赋给一个左值
- += 相加后再赋值 (C += A 等于 C = C + A)
- -= 相减后再赋值 (C -= A 等于 C = C - A)
- *= 相乘后再赋值 (C *= A 等于 C = C * A)
- /= 相除后再赋值 (C /= A 等于 C = C / A)
- %= 求余后再赋值 (C %= A 等于 C = C % A)
- <<= 左移后赋值 (C <<= 2 等于 C = C << 2)
- >>= 右移后赋值 (C >>= 2 等于 C = C >> 2)
- &= 按位与后赋值 (C &= 2 等于 C = C & 2)
- ^= 按位异或后赋值 (C ^= 2 等于 C = C ^ 2)
- |= 按位或后赋值 (C |= 2 等于 C = C | 2)
流程控制
If/else & for & range
注意 else if / else 位置
- if condition1 {
- } else if condition2 {
- } else if condition3 {
- } else {
- }
for循环条件没有小括号
- for i := ; i < ; i++ {
- }
死循环
- for true {
- }
- 可以简写为:
- for {
- }
range
- for i, v := range str {
- }
- package main
- import (
- "fmt"
- )
- func ran(str string) {
- for i, v := range str {
- fmt.Printf("index[%d] val[%c] len[%d]\n", i, v, len([]byte(string(v))))
- }
- }
- func main() {
- ran("Love, 索宁")
- }
- 输出结果:
- index[] val[L] len[]
- index[] val[o] len[]
- index[] val[v] len[]
- index[] val[e] len[]
- index[] val[,] len[]
- index[] val[ ] len[]
- index[] val[索] len[]
- index[] val[宁] len[]
range栗子
switch case
Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch。
- switch var {
- case var1:
- case var2:
- case var3:
- default:
- }
- func sw(num int) {
- switch num {
- case , , :
- fmt.Printf("%s in 1,2,3\n", num)
- case , , :
- fmt.Printf("%s in 4,5,6\n", num)
- fallthrough
- case , , :
- fmt.Printf("%s big 789\n", num)
- default:
- fmt.Printf("default...\n")
- }
- }
switch 栗子一
- func sw2(num int) {
- switch {
- case num > && num < :
- fmt.Printf("%s in 1,2,3\n", num)
- case num > && num < :
- fmt.Printf("%s in 4,5,6\n", num)
- fallthrough
- case num > && num < :
- fmt.Printf("%s big 789\n", num)
- default:
- fmt.Printf("default...\n")
- }
- }
switch 栗子二
- func sw3() {
- switch num := ; {
- case num > && num < :
- fmt.Printf("%s in 1,2,3\n", num)
- case num > && num < :
- fmt.Printf("%s in 4,5,6\n", num)
- fallthrough
- case num > && num < :
- fmt.Printf("%s big 789\n", num)
- default:
- fmt.Printf("default...\n")
- }
- }
switch 栗子三
fallthrough
可以使用fallthrough强制执行后面的case代码。
- package main
- import "fmt"
- func main() {
- switch {
- case false:
- fmt.Println("The integer was <= 4")
- fallthrough
- case true:
- fmt.Println("The integer was <= 5")
- fallthrough
- case false:
- fmt.Println("The integer was <= 6")
- fallthrough
- case true:
- fmt.Println("The integer was <= 7")
- case false:
- fmt.Println("The integer was <= 8")
- fallthrough
- default:
- fmt.Println("default case")
- }
- }
- 运行结果:
- The integer was <=
- The integer was <=
- The integer was <=
fallthrough栗子
label & goto
label要写在for循环的开始而不是结束的地方。直接break退出到指定的位置。
- func lab() {
- LABLE:
- for i := ; i < ; i++ {
- for true {
- i++
- if i == {
- break LABLE
- }
- fmt.Println(i)
- }
- }
- }
goto语句可以跳转到本函数内的某个标签
- func got() {
- i :=
- HERE:
- fmt.Println(i)
- i++
- if i == {
- return
- }
- goto HERE
- }
select
select与switch类似,不过select有较多限制。
每个case语句里必须是一个channel操作;
- select {
- case ch <- :
- //如果0写入,则进行该case
- case <- ch:
- //如果读到数据,则进行该case
- default:
- //如果上面的都没有成功,则进入default处理
- }
- package main
- import (
- "fmt"
- "time"
- )
- /*
- 随机向ch中写入一个0或者1的过程,当然这是个死循环。
- */
- func main() {
- ch := make(chan int, )
- for {
- select {
- case ch <- :
- case ch <- :
- }
- i := <-ch
- fmt.Println(i)
- time.Sleep(time.Second)
- }
- }
select栗子一
- package main
- import (
- "fmt"
- "time"
- )
- /*
- channel超时处理
- 一直没有从ch中读取到数据,但从timeout中读取到了数据
- */
- func main() {
- ch := make(chan bool)
- timeout := make(chan bool, )
- go func() {
- time.Sleep(time.Second*)
- timeout <- true
- }()
- select {
- case <- ch:
- fmt.Println("This is ch.")
- case <- timeout:
- fmt.Println("This is timeout.")
- }
- }
select栗子二(channel超时处理)
函数
Go 语言最少有个 main() 函数。
函数声明告诉了编译器函数的名称,返回类型,和参数。
不支持重载,一个包不能有两个名字一样的函数。
- func function_name( [parameter list] ) [return_types] {
- 函数体
- }
命名返回值的名字(return可以不指定变量):
- func add(a, b int) (c int) {
- c = a + b
- return
- }
栗子一
- func calc(a, b int) (sum int, avg int) {
- sum = a + b
- avg = (a +b)/
- return
- }
栗子二
_标识符,用来忽略返回值:
- func calc(a, b int) (sum int, avg int) {
- sum = a + b
- avg = (a +b)/
- return }
- func main() {
- sum, _ := calc(, )
- }
栗子
函数也是一种类型,一个函数可以赋值给变量
- package main
- import "fmt"
- //申明一个函数类型
- type add_func func(int, int) int
- func add(a, b int) int {
- return a + b
- }
- func operator(op add_func, a int, b int) int {
- return op(a, b)
- }
- func main() {
- c := add
- fmt.Println(c) //0x1087050
- sum := operator(c, , )
- fmt.Println(sum) //
- }
可变参数
其中arg是一个slice,我们可以通过arg[index]依次访问所有参数;通过len(arg)来判断传递参数的个数。
- 0个或多个参数
- func add(arg…int) int {
- }
- 1个或多个参数
- func add(a int, arg…int) int {
- }
- 2个或多个参数
- func add(a int, b int, arg…int) int {
- }
- package main
- import (
- "fmt"
- )
- //返回值指定为sum变量,默认会return这个变量
- func add(a int, b int, arg ...int) (sum int) {
- sum = a + b
- for i := ; i < len(arg); i++ {
- sum += arg[i]
- }
- return
- }
- func concat(s string, arg ...string) string {
- str := s
- for i := ; i < len(arg); i++ {
- str += arg[i]
- }
- return str
- }
- func main() {
- sum := add(, , , , , , )
- fmt.Println(sum) //
- str := concat("nick", " ", "and", " ", "dawn", ".")
- fmt.Println(str) //nick and dawn.
- }
多参数栗子
main & init & defer
main & init
Go程序会自动调用init()和main(),所以你不需要在任何地方调用这两个函数。
defer
- 当函数返回时,执行defer语句;
- 多个defer语句,按先进后出的方式执行;
- defer语句中的变量,在defer声明时确定变量。
- 触发异常也会走defer语句。
- package main
- import "fmt"
- //声明defer时,变量i就为0
- func test1() {
- i :=
- defer fmt.Println(i)
- i++
- return
- }
- //栈,先进先出
- func test2() {
- for i := ; i < ; i++ {
- defer fmt.Printf("->%d", i)
- }
- }
- func main() {
- test1()
- test2()
- }
- 输出:
- ->->->->->
defer 栗子
- package main
- import (
- "fmt"
- )
- func main() {
- defer_call()
- }
- func defer_call() {
- defer func() { fmt.Println("打印前") }()
- defer func() { fmt.Println("打印中") }()
- defer func() { fmt.Println("打印后") }()
- panic("触发异常")
- }
- /*
- 打印后
- 打印中
- 打印前
- panic: 触发异常
- */
defer 栗子二
作用域
- 在函数内部声明的变量叫做局部变量,生命周期仅限于函数内部。
- 在函数外部声明的变量叫做全局变量,生命周期作用于整个包,如果是大写的,则作用于整个程序。
- package main
- import "fmt"
- var name string
- func main() {
- name = "Nick"
- fmt.Println(name)
- f1()
- }
- func f1() {
- name := "Dawn"
- fmt.Println(name)
- f2()
- }
- func f2() {
- fmt.Println(name)
- }
- 输出:
- Nick
- Dawn
- Nick
作用域栗子
匿名函数 & 闭包
匿名函数
匿名函数是由一个不带函数名的函数声明和函数体组成。
- package main
- func main() {
- f := func(x, y int) int {
- return x + y
- }
- f(,)
- ch := make(chan int)
- func (ch chan int) {
- ch <-
- }(ch)
- }
闭包
闭包是一个函数和与其相关的引用环境组合而成的实体。
函数可以存储到变量中作为参数传递给其它函数,能够被函数动态的创建和返回。
- func Adder() func(int) int {
- var x int
- return func(d int) int {
- x += d
- return x
- }
- }
- f := Adder()
- fmt.Println(f()) //
- fmt.Println(f()) //
- fmt.Println(f()) //
- package main
- import (
- "fmt"
- "strings"
- )
- func makeSuffix(suffix string) func(string) string {
- return func(name string) string {
- if !strings.HasSuffix(name, suffix) {
- return name + suffix
- }
- return name
- }
- }
- func main() {
- f1 := makeSuffix(".png")
- fmt.Println(f1("name1")) //name1.png
- fmt.Println(f1("name2")) //name2.png
- f2 := makeSuffix(".jpg")
- fmt.Println(f2("name1")) //name1.jpg
- fmt.Println(f2("name2")) //name2.jpg
- }
闭包栗子二
值传递 & 引用传递
无论是值传递,还是引用传递,传递给函数的都是变量的副本;
值传递是值的拷贝,引用传递是地址的拷贝;
一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。
map、slice、chan、指针、interface默认以引用的方式传递。
new 内置函数 用来分配内存,主要用来分配值类型,比如int、struct,返回的是指针;
make 内置函数 用来分配内存,主要用来分配引用类型,比如chan、map、slice。
程序初始化与执行过程

指针类型(&*)
普通类型,变量存的就是值,也叫值类型;
指针类型,变量存的是一个地址,这个地址存的才是值。
变量是一种占位符,用于引用计算机内存地址;
Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。
获取指针类型所指向的值,使用:*。
一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。
申明如下:
- var age *int //指向整型
- var height *float32 //指向浮点型
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
栗子
- package main
- import "fmt"
- func main() {
- var ptr *int
- num :=
- ptr = &num
- fmt.Println(ptr) //0xc42000e1f8
- fmt.Println(*ptr) //
- *ptr =
- fmt.Println(num) //
- }
- package main
- import "fmt"
- func change(num *int) {
- fmt.Println(num) //0xc42000e1f8
- fmt.Println(*num) //
- *num =
- fmt.Println(num) //0xc42000e1f8
- fmt.Println(*num) //
- }
- func main() {
- num :=
- fmt.Println(&num) //0xc42000e1f8
- change(&num)
- fmt.Println(&num) //0xc42000e1f8
- fmt.Println(num) //
- }
Go语言学习笔记(二)十分钟上手的更多相关文章
- python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码
python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码 python的json.dumps方法默认会输出成这种格式"\u535a\u ...
- python3.4学习笔记(二十五) Python 调用mysql redis实例代码
python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...
- python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法
python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法window安装redis,下载Redis的压缩包https://git ...
- python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字
python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字在字符串里面插入指定分割符的方法,先把字符串变成list然后用join方法变成字符串str=' ...
- python3.4学习笔记(二十) python strip()函数 去空格\n\r\t函数的用法
python3.4学习笔记(二十) python strip()函数 去空格\n\r\t函数的用法 在Python中字符串处理函数里有三个去空格(包括'\n', '\r', '\t', ' ')的函数 ...
- Go语言学习笔记二: 变量
Go语言学习笔记二: 变量 今天又学了一招如何查看go的版本的命令:go version.另外上一个笔记中的代码还可以使用go run hello.go来运行,只是这种方式不会生成exe文件. 定义变 ...
- (C/C++学习笔记) 二十四. 知识补充
二十四. 知识补充 ● 子类调用父类构造函数 ※ 为什么子类要调用父类的构造函数? 因为子类继承父类,会继承到父类中的数据,所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程. ...
- (C/C++学习笔记) 二十二. 标准模板库
二十二. 标准模板库 ● STL基本介绍 标准模板库(STL, standard template library): C++提供的大量的函数模板(通用算法)和类模板. ※ 为什么我们一般不需要自己写 ...
- (C/C++学习笔记) 二十. 文件和流
二十. 文件和流 ● 文件的概念 文件(file) 一. C/C++语言将文件作为字节序列(sequence of characters)来对待,但从编码角度,或说从对字节信息的解释来看,文件分为:文 ...
- R语言学习笔记(十二):零碎知识点(31-35)
31--round(),floor()和ceiling() round()四舍五入取整 floor()向下取整 ceiling()向上取整 > round(3.5) [1] 4 > flo ...
随机推荐
- 每天一个linux命令(目录)
转:http://www.cnblogs.com/peida/archive/2012/12/05/2803591.html 开始详细系统的学习linux常用命令,坚持每天一个命令,所以这个系列为每天 ...
- Hibernate常出现的报错
刚开始学习hibernate的时候,第一次就遇到了空指针异常,结果是我的配置文件处理错误(主要是数据库表的字段与就java实体类的属性名单词写错了):一般是报空指针异常的话,多半是配置文件的问题. 但 ...
- Java设计模式学习记录-简单工厂模式、工厂方法模式
前言 之前介绍了设计模式的原则和分类等概述.今天开启设计模式的学习,首先要介绍的就是工厂模式,在介绍工厂模式前会先介绍一下简单工厂模式,这样由浅入深来介绍. 简单工厂模式 做法:创建一个工厂(方法或类 ...
- stack堆栈容器、queue队列容器和priority_queue优先队列容器(常用的方法对比与总结)
stack堆栈是一个后进先出的线性表,插入和删除元素都在表的一端进行. stack堆栈的使用方法: 采用push()方法将元素入栈: 采用pop()方法将元素出栈: 采用top()方法访问栈顶元素: ...
- SHELL脚本攻略(学习笔记)--2.1 cat
cat命令 输出一个或多个文件的内容. cat [OPTION]... [FILE]... 选项说明 -n:显示所有行的行号 -b:显示非空行的行号 -E:在每行行尾加上$符号 -T:将TAB符号输出 ...
- StreamReader 的ReadLine,Read,ReadToEnd方法
1.ReadLine() 当遇到\n \r 或者是\r\n的时候 此方法返回这前面的字符串,然后内部的指针往后移一位下次从新的地方开始读,直到遇到数据的结尾处返回null,所以经常这样使用 ...
- EF访问数据库报“ExecuteReader 要求已打开且可用的 Connection。连接的当前状态为已关闭。”错误
我发生这个问题的原因是因为我用EF访问数据库时用的用到了两用方式,如下图 第一种方式访问时不会出现此错误,出现错误的是第二种方式,下图是dal层代码 其中红框中的代码是出现错误之后改正的代码,也就是说 ...
- 用MVC5+EF6+WebApi 做一个小功能(四) 项目分层功能以及文件夹命名
在上一节,我们完成了一个项目搭建,我们看到的是一个项目的分层架子,那接下来每一层做什么以及需要引用哪些内容呢?在本节内容我们还逐步拆分每一层的功能,顺带添加package包 Trump.Domain ...
- [Python] 函数基本
使用def 函数名(): 来定义一个函数,函数体一缩进块的形式写,返回结果是return xx 例如: def myAbs(x): if x >= 0: return x else: retur ...
- JSP学习笔记(7)-JSP的文件操作
1.File类 File对象用来获取文件本身的一些信息,例如文件所在目录,文件的长度,文件读写权限等,不涉及文件的读写操作. 创建一个File对象的构造方法有3个: File(String filen ...