Google资深工程师深度讲解Go语言-基础语法(二)
一.变量的定义
1.使用var关键字
- var a,b,c,bool
- var s1,s2 string="hello","world"
- 可放在函数内,或直接放在包内
- 使用var()集中定义变量
2.让编译器自动决定类型
- var a,b,i,s1,s2=true,false,3,"hello","world"
3.使用:=定义变量
- a,b,i,s1,s2:=true,false,3,"hello","world"
- 只能在函数内使用
测试用例代码
package main
import "fmt"
//函数外面定义变量时,必须使用var关键字,不能使用:=
//这些变量作用域,是包内变量,不存在全局变量说法
/*var aa=3
var ss ="kkk"
var bb = true*/
var (
aa = 3
ss = "kkk"
bb = true
)
func variableZeroValue() {
var a int
var b string
fmt.Printf("%d %q\n", a, b)
}
//定义变量类型,不能写在一行
func variableIntValue() {
var a, b int = 3, 4
var s string = "abc"
println(a, b, s)
//fmt.Printf("%d %d %q\n",a,b,s)
}
//省略变量类型,可以写在一行
func varTypeDefValue() {
var a, b, c, s = 3, 4, true, "abc"
println(a, b, c, s)
}
//省略var ,第一次定义使用:冒号来定义,第二次定义时使用等号
func variableValueShorter() {
a, b, c, s := 3, 4, true, "abc"
b = 5
println(a, b, c, s)
}
func main() {
fmt.Println("hello world 33")
variableZeroValue()
variableIntValue()
varTypeDefValue()
variableValueShorter()
fmt.Println(aa,bb,ss)
}
结果
hello world 33
0 ""
3 4 abc
3 4 true abc
3 5 true abc
3 true kkk
二.内建变量类型
s
- bool string
- (u)int (u)int8 (u)int16, (u)int32,(u)int64, uintptr 指针 加u无符号证书,不加u有符号整数,根据操作系统分,规定长度,不规定长度
- byte rune 字符型,go语言的char类型,byte 8位,rune 32位
- float32,float64,complex64,complex128 复数类型,complex64 的实部和虚部都是float32,complex128 实部和虚部都是float64
1.类型转换是强制的,没有隐士类型转换
package main
import (
"fmt"
"math"
"math/cmplx"
)
func euler() {
//c:=3+4i
//fmt.Println(cmplx.Abs(c)) //5
fmt.Printf("%.3f\n",
cmplx.Exp(1i*math.Pi)+1) //(0.000+0.000i)
}
func triangle() {
var a, b int = 3, 4
var c int
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c) //5 强制类型转换
}
func main() {
euler()
triangle()
}
2.变量定义要点:
- 变量类型写在变量名之后
- 编译器可推测变量类型
- 没有char,只有rune
- 原生支持复数类型
//常量
func consts() {
//const filename = "abc.txt"
//const a, b = 3, 4
const(
filename = "abc.txt"
a, b = 3, 4
)
var c int
c = int(math.Sqrt(a*a + b*b))
fmt.Print(filename, c)
}
//枚举
func enums(){
/*const (
c=0
java=1
golang=2
php=3
)*/
const (
c=iota //iota 表示这组是自增值的
_
golang
php
javascript
)
//b kb mb gb tb
const (
b= 1 <<(10*iota)
kb
mb
gb
tb
)
fmt.Println("\n")
fmt.Println(c,javascript,golang,php)//0 4 2 3
fmt.Println(b,kb,mb,gb,tb)//1 1024 1048576 1073741824 1099511627776
}
三.条件语句
if语句
- if的条件里可以赋值
- if的条件里赋值的变量作用域就在这个if语句里
const filename = "/Users/liutao/Desktop/vagrant/go/study/day0803/abc.txt" //注意文件绝对路径
if contents, err := ioutil.ReadFile(filename);err!=nil{
fmt.Println(err)
}else {
fmt.Printf("%s\n", contents)
}
switch panic作用:终端程序执行,并报错
- switch会自动break,除非使用fallthrough
- switch后可以没有表达式
func grade(score int) string {
g := ""
switch {
case score < 0 || score > 100:
panic(fmt.Sprintf("wrong score: %d", score))
case score < 60:
g = "F"
case score < 80:
g = "C"
case score < 90:
g = "B"
case score <= 100:
g = "A"
default:
}
return g
}
//调用
func main() {
fmt.Println(
grade(0),
grade(10),
grade(59),
grade(60),
grade(89),
grade(100),
//grade(120), //panic 报错,中止执行
//grade(-100),
)
}
//执行结果
F F F C B A
四.循环
要点:
- for,if后面的条件没有括号
- if条件里也可以定义变量
- 没有while
- switch不需要break,也可以直接switch多个条件
for 语句
- for的条件里不需要括号
- for的条件里可以省略初始条件,结束条件,递增表达式
- for省略初始条件,相当于while
- for省略初始条件和递增条件,相当于while
- for 初始条件,结束条件,递增表达式都不加就是死循环
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func fors() int {
sum := 0
for i := 1; i <= 100; i++ {
sum += i
}
return sum
}
//1.省略初始条件,相当于while
func converToBin(n int) string {
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
result = strconv.Itoa(lsb) + result //Itoa 转换为字符串
}
return result
}
//2.省略初始条件和递增条件
func printile(filename string) {
file,err:=os.Open(filename)
if err!=nil {
panic(err)
}
scanner:=bufio.NewScanner(file)
//省略初始条件和递增条件
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
//3.初始条件,结束条件,递增表达式都不加就是死循环
func forever() string {
for {
fmt.Println("abc")
}
}
func main() {
fmt.Println(fors())//5050
fmt.Println(
converToBin(5),//101
converToBin(13),//1101
converToBin(0),//空串
)
//forever()
printile("/Users/liutao/Desktop/vagrant/go/study/day0803/abc.txt")
}
//执行结果
5050
101 1101
/**下面文件内容**/
lxw
test
1234
hehh
五.函数
-
函数返回多个值时,可以起名字 仅用于非常简单的函数 对于调用者而言没有区别 返回值类型写在后面(go 变量和返回值都是 名在前,类型在后) go可返回多个值,php只能返回一个值(字符串或数组,对象) 函数作为参数(匿名函数) go没有默认参数和可选参数,但有可变参数列表
-
package main import ( "fmt" "math" "reflect" "runtime" ) func eval(a, b int, op string) (int, error) { switch op { case "+": return a + b, nil case "-": return a - b, nil case "*": return a * b, nil case "/": //return a / b q, _ := div(a, b) return q, nil default: //panic("unsupported operation:" + op) //终端执行 return 0, fmt.Errorf("unsupported operation: %s", op) //不中断,0 unsupported operation: X } } //多返回值 func div(a, b int) (q, r int) { return a / b, a % b } func apply(op func(int, int) int, a, b int) int { p := reflect.ValueOf(op).Pointer() opName := runtime.FuncForPC(p).Name() fmt.Printf("calling function %s with args"+"(%d,%d)\n", opName, a, b) return op(a, b) } func pow(a, b int) int { return int(math.Pow(float64(a), float64(b))) } //可变参数列表 func sum(nubers ...int)int{ s:=0 for i:=range nubers{ s+=nubers[i] } return s } func main() { //fmt.Println(eval(13, 4, "X")) if result, err := eval(13, 4, "X"); err != nil { fmt.Println("error:", err) //error: unsupported operation: X } else { fmt.Println(result) } q, r := div(13, 3) fmt.Println(q, r) //fmt.Println(apply(pow, 3, 4)) fmt.Println(apply( func(a int, b int) int { return int(math.Pow( float64(a), float64(b))) }, 3, 4)) fmt.Println(sum(1,2,3,4,5)) //15 }
六.指针
-
指针不能运算
-
go语言只有值传递一种方式
package main import "fmt" //go 语言只有值传递一种方式 //交换a,b 的值 * 指针类型 //方法一 /*func swap(a,b *int){ *b,*a=*a,*b }*/ //方法二 func swap(a,b int)(int,int) { return b,a } func main() { a,b:=3,4 //方法一 //swap(&a,&b) //方法二 a,b=swap(a,b) fmt.Println(a,b) //4,3 }
赞赏码
非学,无以致疑;非问,无以广识