go 第二章--顺序编程

变量 相当于是对一块数据存储空间的命名。


  • 定义变量
var v1 int
var v2 string
var v3 [10]int // 数组
var v4 []int // 数组切片
var v5 struct {
f int
}
var v6 *int // 指针
var v7 map[string]int // map, key为string类型, value为int类型
var v8 func(a int) int

懒人写法

var (
v1 int
v2 string
)
  • go变量初始化
var v1 int = 10 // 正确的使用方式1
var v2 = 10 // 正确的使用方式2,编译器可以自动推导出v2的类型
v3 := 10 // 正确的使用方式3,编译器可以自动推导出v3的类型

出现在:=左侧的变量不应该是已经被声明过的,否则会导致编译错误。

  • 变量赋值
var v10 int
v10 = 123

//特别
i, j = j, i //i ,j交换,多重赋值
  • 匿名变量
func GetName() (firstName, lastName, nickName string) {
	return "May", "Chan", "Chibi Maruko"
}
//若只想获得nickName,则函数调用语句可以用如下方式编写:
_, _, nickName := GetName()
  • 常量是指编译期间就已知且不可改变的值。常量可以是数值类型(包括整型、
    浮点型和复数类型)、布尔类型、字符串类型

字面常量 go里无类型,只要这个常量在相应类型的值域
范围内,就可以作为该类型的常量,比如上面的常量12,它可以赋值给int、 uint、 int32、
int64、 float32、 float64、 complex64、 complex128等类型的变量。

常量定义

const Pi float64 = 3.14159265358979323846
const zero = 0.0 // 无类型浮点常量
const (
size int64 = 1024
eof = -1 // 无类型整型常量
)
const u, v float32 = 0, 3 // u = 0.0, v = 3.0,常量的多重赋值
const a, b, c = 3, 4, "foo"
// a = 3, b = 4, c = "foo", 无类型整型和字符串常

const mask = 1 << 3  //右值是常量表达式
  • 常量定义右值不能为运行时才出结果的值,会报错。

  • 预定义常量
    Go语言预定义了这些常量: true、 false和iota。
    iota比较特殊,可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被
    重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1。

const (		   // iota被重设为0
	c0 = iota // c0 == 0
	c1 = iota // c1 == 1
	c2 = iota // c2 == 2
)
const (
	a = 1 << iota // a == 1 (iota在每个const开头被重设为0)
	b = 1 << iota // b == 2
	c = 1 << iota // c == 4
)
const (
	u = iota * 42 // u == 0
	v float64 = iota * 42 // v == 42.0
	w = iota * 42 // w == 84
)
const x = iota // x == 0 (因为iota又被重设为0了)
const y = iota // y == 0 (同上)

const ( // iota被重设为0
	c0 = iota // c0 == 0
	c1 // c1 == 1
	c2 // c2 == 2
)
const (
	a = 1 <<iota      // a == 1 (iota在每个const开头被重设为0)
	b                      // b == 2
	c                      // c == 4
)
  • 枚举
const (
	Sunday = iota
	Monday
	Tuesday
	Wednesday
	Thursday
	Friday
	Saturday
	numberOfDays // 这个常量没有导出
)
  • 类型
Go语言内置以下这些基础类型:
 布尔类型: bool。
 整型: int8、 byte、 int16、 int、 uint、 uintptr等。
 浮点类型: float32、 float64。
 复数类型: complex64、 complex128。
 字符串: string。
 字符类型: rune。
 错误类型: error。
此外, Go语言也支持以下这些复合类型:
 指针(pointer)
 数组(array)
 切片(slice)
 字典(map)
 通道(chan)
 结构体(struct)
 接口(interface)

slice切片

1.slice数据结构

struct{
	p *void  //一个指向原生数组的指针
	num  *int  //数组切片中的元素个数
	len  *int   // 数组切片已分配的存储空间
}

2.创建数组切片

  • 基于数组
package main
import "fmt"
func main() {
	// 先定义一个数组
	var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	// 基于数组创建一个数组切片
	var mySlice []int = myArray[:5]
	fmt.Println("Elements of myArray: ")
	for _, v := range myArray {
		fmt.Print(v, " ")
	}
	fmt.Println("\nElements of mySlice: ")
	for _, v := range mySlice {
		fmt.Print(v, " ")
	}
	fmt.Println()
}
#运行结果为:
Elements of myArray:
1 2 3 4 5 6 7 8 9 10
Elements of mySlice:
1 2 3 4 5
  • 直接创建
创建一个初始元素个数为5的数组切片,元素初始值为0:
mySlice1 := make([]int, 5)
创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间:
mySlice2 := make([]int, 5, 10)
直接创建并初始化包含5个元素的数组切片:
mySlice3 := []int{1, 2, 3, 4, 5}

3.动态增减元素

package main
import "fmt"
func main() {
	mySlice := make([]int, 5, 10)
	
	fmt.Println("len(mySlice):", len(mySlice)) //len 计算切片的元素个数
	fmt.Println("cap(mySlice):", cap(mySlice))  //cap 计算切片已分配的存储空间
}
mySlice = append(mySlice, 1, 2, 3)
函数append()的第二个参数其实是一个不定参数,我们可以按自己需求添加若干个元素,
甚至直接将一个数组切片追加到另一个数组切片的末尾:
mySlice2 := []int{8, 9, 10}
// 给mySlice后面添加另一个数组切片
mySlice = append(mySlice, mySlice2...)
等价
mySlice = append(mySlice, 8, 9, 10)
//加上省略号相当于把mySlice2包含的所有元素打散后传入

4.基于数组切片创建数组切片

oldSlice := []int{1, 2, 3, 4, 5}
newSlice := oldSlice[:3] // 基于oldSlice的前3个元素构建新数组切片

5.内容复制

slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置

map

map是一堆键值对的未排序集合

package main
import "fmt"
// PersonInfo是一个包含个人详细信息的类型
type PersonInfo struct {
	ID string
	Name string
	Address string
}
func main() {
	var personDB map[string] PersonInfo  //声明
	personDB = make(map[string] PersonInfo)  //创建
	// 往这个map里插入几条数据
	personDB["12345"] = PersonInfo{"12345", 			"Tom", "Room 203,..."}
	personDB["1"] = PersonInfo{"1", "Jack", "Room 101,..."}
	// 从这个map查找键为"1234"的信息
	person, ok := personDB["1234"]
	// ok是一个返回的bool型,返回true表示找到了对应的数据
	if ok {
		fmt.Println("Found person", person.Name, "with ID 1234.")
	} else {
		fmt.Println("Did not find person with ID 1234.")
	}
	delete(personDB, "1") //删除map中的一个元素
}

函数定义

package mymath
import "errors"
func Add(a int, b int) (ret int, err error) {
	if a < 0 || b < 0 { // 假设这个函数只支持两个非负数字的加法
		err= errors.New("Should be non-negative numbers!")
		return
	}
	return a + b, nil // 支持多重返回值
}

函数调用

import "mymath"// 假设Add被放在一个叫mymath的包中
// ...
c := mymath.Add(1, 2)

小写字母开头的函数只在本包内可见,大写字母开头的函数才
能被其他包使用。这个规则也适用于类型和变量的可见性。

不定参数

func myfunc(args ...int) {
	for _, arg := range args {
		fmt.Println(arg)
	}
}

1.不定参数类型
2.不定参数的传递
3.任意类型的不定参数

package main
import "fmt"
func MyPrintf(args ...interface{}) {
	for _, arg := range args {
		switch arg.(type) {
			case int:
				fmt.Println(arg, "is an int value.")
			case string:
				fmt.Println(arg, "is a string value.")
			case int64:
				fmt.Println(arg, "is an int64 value.")
			default:
				fmt.Println(arg, "is an unknown type.")
			}
	}
}
func main() {
	var v1 int = 1
	var v2 int64 = 234
	var v3 string = "hello"
	var v4 float32 = 1.234

	MyPrintf(v1, v2, v3, v4)
}
该程序的输出结果为:
1 is an int value.
234 is an int64 value.
hello is a string value.
1.234 is an unknown type.

多指返回
匿名函数与闭包

package main
import (
	"fmt"
)
func main() {
	var j int = 5
	a := func()(func()) {
	var i int = 10
	return func() {
		fmt.Printf("i, j: %d, %d\n", i, j)
	}
}()
a()
j *= 2
a()
}
上述例子的执行结果是:
i, j: 10, 5
i, j: 10, 10

错误处理

1.error接口
2.defer 一个函数中可以存在多个defer语句,因此需要注意的是, defer语句的调用是遵照
先进后出的原则,即最后一个defer语句将最先被执行.
3.panic()和recover()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值