Go语言学习-基本语法

基本语法

变量的定义

使用var关键字

  • var a,b,c bool
  • var s1,s2 string = “hello”,”world”
  • 可放在函数内,或直接放在包内
  • 使用var()集中定义变量

让编译器自动决定类型

  • var a,b,i,s1,s2 = true,false,3,”hello”,”world”

使用:=定义变量 (推荐方式)

  • a,b,i,s1,s2 := true,false,3,”hello”,”world”
  • 只能在函数内部使用

代码演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package main

import "fmt"

// 外部变量定义1
var aa = 3 // 外部定义变量,不能用冒号的方式;也不是全部变量,是属于包内部变量,go不存在全局变量
var ss = "kkk"
var bb = true

// 外部变量定义2
var ( // 多个变量一起定义
ff = 11
hh = true
sss = "chongqing"
)

// 不给初值
func varValue() {
var a, c int // 默认值为0 可以多个
var s string // 默认为空值
fmt.Printf("%d %q %d\n", a, s, c)
}

// 变量初值定义
func varInit() {
var a, c int = 1, 5 // 赋初值 可以多个
var b string = "你好" // 赋初值
fmt.println(a, b, c)
}

// 不需要type的定义
func noTypeVar() {
var a, b, c = 1, false, "xiexiang" // 不规定类型可以多个类型同时定义
fmt.println(a, b, c)
}

// 最简洁写法
func noVar() {
a, b, c := 2, "xiexiang", true // 可以多个不同类型一起定义,中间需要:=
b = "chongqing" // 赋值的时候不能有冒号
fmt.println(a, b, c)
}

// 主入口
func main() {
fmt.Println("hello world!")
varValue()
varInit()
noTypeVar()
noVar()
}

内建变量类型

  • bool, string
  • (u)init, (u)int8, (u)int16, (u)int32, (u)int64, uintptr(指针)
  • byte, rune(char类型)
  • float32, float64, complex64, complex128

复数的回顾:
2022

复数的演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

package main

import (
"fmt"
"math/cmplx"
)

func complexShow() {
c := 3 + 4i
fmt.Println(cmplx.Abs(c))
}

// 主入口
func main() {
complexShow() // 运行结果为5
}

强制类型转换:

  • 类型转换是强制的
  • var a, b int = 3, 4
  • var c int = math.Sqrt(aa + bb) // 这样会报错,不存在隐式类型转换
  • var c int = int(math.Sqrt(float64(aa + bb))) // 必须显式转换 math.Sqrt:平方根,又叫二次方根,表示为〔±√ ̄〕 验证的是勾股定理

代码演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func typeChange() {
var a, b int = 3, 4
var c int
c = int(math.Sqrt(float64(a*a + b*b))) // 必须显式的类型转换
fmt.println(c)

var ss = 85.8
var bb float64 = 100
fmt.println(int(ss + bb))
}

// 主入口
func main() {
typeChange() // 结果为5 185
}

常量与枚举

常量:

  • const filename = “abc.txt” // 暂时不做全部大写,GO语言的大小写是有含义的
  • const 数值可作为各种类型使用 (没有强制限制类型的情况下)
  • const a,b = 3,4
  • var c int = int(math.Sqrt(aa + bb)) // 这里就不需要强制转换
1
2
3
4
5
6
7
8
func consts() {
// 暂时不做全大写
const filename = "abc.txt"
const (
file = "acc.txt"
a, b = 3, 4
)
}

枚举:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func enums() {
const ( // 枚举必须给值
cpp = 0
java = 1
php = 2
python = 3
)

const (
cpp = iota // 自增值,从0开始
java
php
python
)
const (
b = 1 << (10 * iota) // 可以加入表达式
kb
mb
gb
tb
pb
)
fmt.Println(b, kb, mb, gb, tb, pb)
}

变量定义的要点回顾:

  • 变量类型写在变量名称之后
  • 编译器可以推测变量的类型
  • 没有char,只有rune
  • 原生支持复数类型

条件语句

if:if的语句里面不需要括号

  • if的条件里面可以赋值
  • if的条件里面赋值的变量作用域就在这个if语句里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
"fmt"
"io/ioutil"
)

func main() {
const filename = "abc.txt"
contents, err := ioutil.ReadFile(filename) // 读取文件内容
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("%s \n", contents)
}
}

// 另一种写法
func main() {
const filename = "abc.txt"
// contents,err 只作用于if里面,if里面可以写多个表达式
if contents, err := ioutil.ReadFile(filename); err != nil {
fmt.Println(err)
} else {
fmt.Printf("%s \n", contents)
}
}

switch:

  • switch 会自动break,除非使用fallthrough
  • switch 后面可以没有表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func eval(a, b int, op string) int {
var res int
switch op {
case "+":
res = a + b
case "-":
res = a - b
case "*":
res = a * b
case "/":
res = a / b
default:
panic("无法识别的运算符:" + op)
}
return res
}

func main() {
res := eval(1, 6, "/")
fmt.Println(res)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// switch 后面没有表达式的写法
func grade(score int) string {
switch {
case score < 0 || score > 100:
panic(fmt.Sprintf("错误的数值:%d", score))
case score < 60:
return "F"
case score < 80:
return "C"
case score < 90:
return "B"
case score <= 100:
return "A"
default:
return "无法计算哦"
}
}

func main() {
fmt.Println(
grade(20),
grade(78),
grade(87),
grade(94),
)
}

循环

  • for 循环条件里不需要括号
  • for 的条件里可以省略初始条件,结束条件,递增表达式
  • for 省略初始条件,相当月while
  • 无限循环
1
2
3
4
5
6
7
func forTest() int {
sum := 0
for i := 1; i <= 100; i++ {
sum += i
}
return sum
}

for和if的结合运用 (九九乘法表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 九九乘法表
func multiplication() {
for i := 1; i < 10; i++ {
for j := 1; j < 10; j++ {
if i >= j {
fmt.Print(fmt.Sprintf("%dx%d=%d ", j, i, j*i))
}
if i == j {
fmt.Println(" ")
}
}
}
}

结果:
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
1x4=4 2x4=8 3x4=12 4x4=16
1x5=5 2x5=10 3x5=15 4x5=20 5x5=25
1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
1
2
3
4
5
6
7
8
9
// 数值转二进制 - 省略初始条件
func convertToBin(n int) string {
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
result = strconv.Itoa(lsb) + result // strconv.Itoa 整型转字符串
}
return result
}
1
2
3
4
5
6
7
8
9
10
11
// 读取文件 - 省略递增条件
func printFile(filename string) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
1
2
3
4
5
6
// 死循环
func forever() {
for {
fmt.Println(1)
}
}

函数

  • 函数可以返回多个值
  • 函数返回多个值时可以起名字
  • 仅用于比较简单的函数
  • 对于调用者而言没有区别
  • 函数可以作为参数
  • 函数不存在重载、函数参数默认值、可选参数
1
2
3
4
5
6
7
8
// 返回值可以指定变量,也可以直接指定类型
func div(a, b int) (int, int) {
return a / b, a % b
}

func div1(a, b int) (q, r int) {
return a / b, a % b
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 通常使用两个返回参数,一个表示结果,一个标识错误信息
func scoreTotal(score int) (string, error) {
if score < 60 {
return "C", nil
} else if score >= 60 && score < 80 {
return "B", nil
} else if score >= 80 && score <= 100 {
return "A", nil
} else {
//panic("超出区间值:" + score) // 这里不用panic返回,调用的地方无法捕获
return "", fmt.Errorf("超出区间值:%d", score) // 注意返回错误需要 fmt.Errorf
}
}

func main() {
// 处理结果
if result, err := scoreTotal(1000); err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("result:", result)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 函数可以作为参数
/*
- 调用apply方法会传a,b两个参数,这两个参数会放入到op方法体进行执行,而op方法体又是一个自定义的函数
*/
func apply(op func(int, int) int, a, b int) int {
return op(a, b)
}


func main() {
// 调用apply函数的时候第一个参数传一个匿名函数
fmt.Println(
apply(func(a int, b int) int {
return int(math.Pow(float64(a), float64(b))) // math.Pow(x, y) x的y次方
}, 2, 4),
)
}

结果为:16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 设置无限个参数    ...int 就是不限制参数的个数 
func sumArgs(numbers ...int) int {
sum := 0
for i := range numbers {
sum += numbers[i]
}
return sum
}

func main() {
fmt.Println(sumArgs(1, 2, 3, 4, 5, 6, 7))
}


结果:28

指针

  • go语言只有值传递,没有引用传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

// 数值交换
func swap(a, b *int) {
*b, *a = *a, *b
}

// 指针
func main() {
a, b := 3, 4
swap(&a, &b)
fmt.Println(a, b)
}
谢翔 wechat
坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束感谢您的阅读-------------
0%