语句
if
var a = 1
if a > 0 {
fmt.Println("a>0")
} else if a == 0 {
fmt.Println("a==0")
} else {
fmt.Println("a<0")
}
//在条件中可以声明赋值,但不能用var,只能用:=,声明的变量的作用域是当前if语句中
if b := 1; b > 0 {
fmt.Println("b>0")
} else if b == 0 {
fmt.Println("b==0")
} else {
fmt.Println("b<0")
}
switch
func f1(a, b int, operator string) {
switch operator {
case "+":
fmt.Printf("%d%s%d=%d\n", a, operator, b, a+b)
case "-":
fmt.Printf("%d%s%d=%d\n", a, operator, b, a-b)
case "*":
fmt.Printf("%d%s%d=%d\n", a, operator, b, a*b)
case "/":
fmt.Printf("%d%s%d=%d\n", a, operator, b, a/b)
default:
//panic(fmt.Sprintf("不支持的运算符:%s", operator))
panic("不支持的运算符:" + operator)
}
}
func f2(score int) {
switch {
case score >= 80 && score <= 100:
fmt.Println("优秀")
case score >= 60 && score < 80:
fmt.Println("良好")
case score >= 0 && score < 60:
fmt.Println("不及格")
default:
//panic(fmt.Sprintf("不合法的分数值:%d", score))
panic("不合法的分数值:" + strconv.Itoa(score))
}
}
- case会自动加上break,不用手动加
- switch后可以有表达式,也可以没有
- case中可以写条件,可以写多个条件,作用类似于if语句
for
for i := 0; i < 10; i++ {
fmt.Println(i)
}
arr := []string{"a", "b", "c", "d"}
//遍历数组,有2个变量时,第一个是下标,第二个是元素值
for index, value := range arr {
fmt.Println(index, value)
}
//如果不使用其中某个变量,可写成_
for _, value := range arr {
fmt.Println(value)
}
//如果只有一个变量,则为下标
for index := range arr {
fmt.Println(index)
}
//初始值、循环条件、变量变化表达式均可缺省,全部缺省时为无限循环
for {
fmt.Println("ok")
}
- golang中没有while循环,while循环可以转换为for,使用for即可
- 内建容器都可以用for range遍历
函数
函数的定义、使用
- golang的参数、变量声明都是变量名在前,类型在后
- golang函数的返回值类型放在最后,形参没有默认值
//无返回值时不用写返回值类型
func f1(name string, age int) {
fmt.Printf("执行f1,name=%s,age=%d\n", name, age)
}
//如果参数类型相同,可以合写成 参数名1,参数名2 类型
func f2(a, b int, operator string) int {
switch operator {
case "+":
return a + b
case "-":
return a - b
case "*":
return a * b
case "/":
return a / b
default:
panic("不支持的运算符:" + operator)
}
}
//可以有多个返回值,返回值类型放在()中
func f3(a, b int) (int, int) {
return b, a
}
func main() {
f1("chy", 20)
result := f2(10, 20, "+")
fmt.Printf("f2()返回的值:%d\n", result)
a, b := f3(10, 20)
fmt.Printf("f3()返回的值:%d\t%d\n", a, b)
}
返回值名称
/*
可以给返回值起名字,这样Ctrl+ALt+V补全时会使用对应的变量名来接收
不建议这样做,到处都是变量名,看起来有些混乱,如果要用,尽量只用在简单的函数上
*/
func f1(a, b int) (sum, diff int) {
return a + b, a - b
}
func main() {
sum, diff := f1(100, 10)
fmt.Println(sum, diff)
}
参数个数可变的函数
//参数个数可变的函数,使用数组接受参数
func sum(values ...int) int {
sum := 0
for _, value := range values {
sum += value
}
return sum
}
func main() {
sum := sum(1, 2, 3, 4)
fmt.Println(sum)
}
函数作为参数
//函数可以作为参数。此处oper代表函数名,func(int, int) int是函数原型
func apply(oper func(int, int) int, a, b int) int {
return oper(a, b)
}
func main() {
result := apply(func(a int, b int) int {
return a + b
}, 10, 20)
fmt.Println(result)
}
函数闭包
闭包:返回值是函数,返回函数中使用的局部变量也会保存在内存中
//func(int) int是函数原型,返回值类型是这种类型的函数
func adder() func(int) int {
sum := 0
//返回的函数中包含了变量sum,sum随返回的函数一起被保存在内存中
return func(a int) int {
sum += a
return sum
}
}
func main() {
//用一个变量保存addr()返回的函数,可以把f做函数名来调用返回的函数
f := adder()
for i := 1; i < 10; i++ {
fmt.Printf("0+...+%d=%d\n", i, f(i))
}
}
- i=1时,第一次调用f(i),sum=0+1=1,sum=1随函数被保存在内存中
- i=2时,第二次调用f(i),sum=1+2=3 ,sum使用的是被保存在内存中的值,不是初始值
可见性规则
与其它语言的标识符命名规则不同,golang的标识命名有特殊含义,标识着可见性,不能随便大小写。
如果常量名、变量名、结构体名、函数名等
- 以小写开头,则只在当前包中可见,可在当前中直接使用
- 以大写开头,则是公共变量,在其它包中可见,可导入使用
假设有一个目录D:/gopath/demo,GOPATH是D:/gopath,demo是项目根目录,demo下有2个包:package1、main
package1
var Name = "chy"
func F() {
fmt.Println("正在执行F()...")
}
//内部字段名也要大写,不然不能访问、操作内部字段
type Node struct {
Value int
Pre, Next *Node
}
main
import (
"fmt"
//导入时取GOPATH后面的路径,直到包名
"demo/package1"
)
func main() {
//通过包名来引用
fmt.Println(package1.Name)
package1.F()
head := package1.Node{Value: 10}
fmt.Println(head.Value)
fmt.Println(head.Pre)
}
导包时会先将import中的包的相对路径拼接在GOROOT后面,看存不存在,如果不存在,再拼接到GOPATH后面,看存不存在。
官方推荐把所有的golang项目、第三方库都放在GOPATH的src目录下。