Go的基础语法
声明变量
var
var s1 string
s1 = "Learn Go!"
// 一次声明多个变量
var b, c int = 1, 2
var d = true
// 匿名赋值
_ , e = 10, 20
_ 是匿名赋值的意思,也就是该该值被忽略了
:=
Go自动识别类型
s1 := "Learn Go!" // string
b, c := 1, 2 // int
d := true // bool
基本类型
数字 Numbers
布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。 或 b := true
数字 Numbers
Int
| 序号 | 类型和描述 |
|---|---|
| 1 | uint8 无符号 8 位整型 (0 到 255) |
| 2 | uint16 无符号 16 位整型 (0 到 65535) |
| 3 | uint32 无符号 32 位整型 (0 到 4294967295) |
| 4 | uint64 无符号 64 位整型 (0 到 18446744073709551615) |
| 5 | int8 有符号 8 位整型 (-128 到 127) |
| 6 | int16 有符号 16 位整型 (-32768 到 32767) |
| 7 | int32 有符号 32 位整型 (-2147483648 到 2147483647) |
| 8 | int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807) |
float
| 序号 | 类型和描述 |
|---|---|
| 1 | float32 IEEE-754 32位浮点型数 |
| 2 | float64 IEEE-754 64位浮点型数 |
| 3 | complex64 32 位实数和虚数 |
| 4 | complex128 64 位实数和虚数 |
其它
| 序号 | 类型和描述 |
|---|---|
| 1 | byte 类似 uint8 |
| 2 | rune 类似 int32 |
| 3 | uint 32 或 64 位 |
| 4 | int 与 uint 一样大小 |
| 5 | uintptr 无符号整型,用于存放一个指针 |
字符串 Strings
// ┌────┬────┬────┬────┬─────┬─────┐
// | 2 | 3 | 5 | 7 | 11 | 13 |
// └────┴────┴────┴────┴─────┴─────┘
// 0 1 2 3 4 5
primes := [...]int{2, 3, 5, 7, 11, 13}
fmt.Println(len(primes)) // => 6
// 输出:[2 3 5 7 11 13]
fmt.Println(primes)
// 与 [:3] 相同,输出:[2 3 5]
fmt.Println(primes[0:3]) //包头不包尾
字符串函数
package main
import (
"fmt"
s "strings"
)
func main() {
/* 需要将字符串导入为 s */
fmt.Println(s.Contains("test", "e"))
/* 内置 */
fmt.Println(len("hello")) // => 5
// 输出: 101
fmt.Println("hello"[1])
// 输出: e
fmt.Println(string("hello"[1]))
}
函数API
| 函数 | 返回值 |
|---|---|
| Contains("test", "es") | true |
| Count("test", "t") | 2 |
| HasPrefix("test", "te") | true |
| HasSuffix("test", "st") | true |
| Index("test", "e") | 1 |
| Join([]string{"a", "b"}, "-") | a-b |
| Repeat("a", 5) | aaaaa |
| Replace("foo", "o", "0", -1) | f00 |
| Replace("foo", "o", "0", 1) | f0o |
| Split("a-b-c-d-e", "-") | [a b c d e] |
| ToLower("TEST") | test |
| ToUpper("test") | TEST |
fmt.Printf
package main
import (
"fmt"
"os"
)
type point struct {
x, y int
}
func main() {
p := point{1, 2}
fmt.Printf("%v\n", p) // => {1 2}
fmt.Printf("%+v\n", p) // => {x:1 y:2}
fmt.Printf("%#v\n", p) // => main.point{x:1, y:2}
fmt.Printf("%T\n", p) // => main.point
fmt.Printf("%t\n", true) // => TRUE
fmt.Printf("%d\n", 123) // => 123
fmt.Printf("%b\n", 14) // => 1110
fmt.Printf("%c\n", 33) // => !
fmt.Printf("%x\n", 456) // => 1c8
fmt.Printf("%f\n", 78.9) // => 78.9
fmt.Printf("%e\n", 123400000.0) // => 1.23E+08
fmt.Printf("%E\n", 123400000.0) // => 1.23E+08
fmt.Printf("%s\n", "\"string\"") // => "string"
fmt.Printf("%q\n", "\"string\"") // => "\"string\""
fmt.Printf("%x\n", "hex this") // => 6.86578E+15
fmt.Printf("%p\n", &p) // => 0xc00002c040
fmt.Printf("|%6d|%6d|\n", 12, 345) // => | 12| 345|
fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45) // => | 1.20| 3.45|
fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45) // => |1.20 |3.45 |
fmt.Printf("|%6s|%6s|\n", "foo", "b") // => | foo| b|
fmt.Printf("|%-6s|%-6s|\n", "foo", "b") // => |foo |b |
s := fmt.Sprintf("a %s", "string")
fmt.Println(s)
fmt.Fprintf(os.Stderr, "an %s\n", "error")
}
指针 Pointers
Go是基于C开放而来的,固指针这一特性也被继承到了。
func main () {
b := *getPointer()
fmt.Println("Value is", b)
}
func getPointer () (myPointer *int) {
a := 234
return &a
}
//申明指针的时候,如果没有指向某个变量,默认值为nil
//不能直接进行操作,包括读写
var p *int
*p = 123 // panic nil pointer
//而用new返回的是有默认值的指针, 为数据类型的默认值
func main(){
//有一块内存存放了10,它的地址由系统自动分配,别名是a
a := 10
//内存存放的10变成了20
a = 20
var p *int
p = &a //或者直接写 p := &a
//上面的p是一个指针,通过 *p 的方式同样可以访问 变量a指向 的内存
/*当你动态申请内存的时候,指针的存在意义之一就被体现出来了*/
ptr := new(int)
//申请了一块内存空间,没有办法指定别名,new()返回内存地址,用指针接收
//此时并没有变量能直接指向这块内存,所以只能通过内存地址来访问
}
切片 Slices
一般的数组长度是固定的,进行操作时比较麻烦,而切片就能很好解决这个问题
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s)
fmt.Println(s[1])
fmt.Println(len(s))
fmt.Println(s[1:3])
slice := []int{2, 3, 4}
常量 Constans
const s string = "constant"
const Phi = 1.618
const n = 500000000
const d = 3e20 / n
常量声明可以使用 iota常量生成器 初始化,它用于 生成一组以相似规则初始化的常量,但是不用每行都 写一遍初始化表达式。 注意:
- 在一个const声明语句中,在第一个声明的常量所在的行,iota被置为0,然后在每一个有常量声明的行加一。
- 写在同一行的值是相同的
const (
a = iota
b
c
)
// a = 0, b = 1, c = 2
类型转换
Go语言中不允许隐式转换,所有类型转换必须显式声明(强制转换),而且转换只能发生在两种相互兼容的类型之间。
i := 90
f := float64(i)
u := uint(i)
// 将等于字符Z
s := string(i)
如何获取int字符串?
i := 90
// 需要导入“strconv”
s := strconv.Itoa(i)
fmt.Println(s) // Outputs: 9
条件控制(循环)
条件控制
a := 10
if a > 20 {
fmt.Println(">")
} else if a < 20 {
fmt.Println("<")
} else {
fmt.Println("=")
}
if 中的语句
x := "hello go!"
if count := len(x); count > 0 {
fmt.Println("Yes")
}
if _, err := doThing(); err != nil {
fmt.Println("Uh oh")
}
Switch
x := 42.0
switch x {
case 0:
case 1, 2:
fmt.Println("Multiple matches")
case 42: // Don't "fall through".
fmt.Println("reached")
case 43:
fmt.Println("Unreached")
default:
fmt.Println("Optional")
}
For loop
for i := 0; i <= 10; i++ {
fmt.Println("i: ", i)
}
Range 循环
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println("sum:", sum)
For 循环
i := 1
for i <= 3 {
fmt.Println(i)
i++
}
关键字
Continue 与 break
for i := 0; i <= 5; i++ {
if i % 2 == 0 {
continue
}
fmt.Println(i)
}
//--------------------------
for {
fmt.Println("loop")
break
}
Golang 结构和Maps
定义
package main
import (
"fmt"
)
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X, v.Y) // => 4 2
}
参见:结构(Structs)
字面量
v := Vertex{X: 1, Y: 2}
// Field names can be omitted
v := Vertex{1, 2}
// Y is implicit
v := Vertex{X: 1}
您还可以输入字段名
Maps
m := make(map[string]int)
m["k1"] = 7
m["k2"] = 13
fmt.Println(m) // => map[k1:7 k2:13]
v1 := m["k1"]
fmt.Println(v1) // => 7
fmt.Println(len(m)) // => 2
delete(m, "k2")
fmt.Println(m) // => map[k1:7]
_, prs := m["k2"]
fmt.Println(prs) // => false
n := map[string]int{"foo": 1, "bar": 2}
fmt.Println(n) // => map[bar:2 foo:1]
指向结构的指针
v := &Vertex{1, 2}
v.X = 2