Go语言学习笔记3:切片-指针-结构体-错误处理

参考资料:


切片

slice := make([]int, 5)

完整实践:

package main

import "fmt"

func slice(s[]int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
//切片详情

func main(){
/*
	var test_ar = [3]int{1,3,2}
	fmt.Print(test_ar)

	s := test_ar[1:3]
//对数组test_ar进行切片

	var s = []int{4,3,2,1}
//切片的一种声明方式
	s := []int{5,4,3,2}
//切片的另一种声明方式
	fmt.Print(s)
*/

/*
var a = [6]int{1,2,3,4,5,6}

s := a[:]
slice(s)

s = s[:2]
slice(s)

s = s[2:]
slice(s)

fmt.Print(a)
*/

/*
var s = []int
//这种切片声明方式没有指定切片的容量和长度,会使该切片无法使用。默认值为nil
//长度为0的切片称之为空切片

s = append(s, 32)
//如果要使用必须使用append扩充容量
slice(s)

s := make([]int, 2, 5)
//使用make关键词创建切片
*/

//...三个点是展开切片元素:
s1 := []int{1,2,3,4,5}
s2 := []int{44, 55, 66, 77}
s := append(s1, s2...)
fmt.Println(s)

//append练习 
add()
//实现队列应用 
msg()
//实现堆栈应用 
stack()
}

func stack(){
	//应用场景:堆栈 FILO先进后出
	//生成栈
	stack1 := []int{}

	//堆栈input
	stack1 = append(stack1, 1, 2, 3, 4, 5)
	fmt.Println(stack1)	//查看队列完整信息

	//获取栈底
	data := stack1[(len(stack1)-1)]
	fmt.Println(data)	//输出信息

	//删除栈底
	stack1 = stack1[:(len(stack1)-1)]
	fmt.Println(stack1)	//查看队列完整信息
}

func msg(){
	//应用场景:队列 FIFO先进先出
	//生成队列
	qun1 := []int{}

	//写入队列input
	qun1 = append(qun1, 1, 2, 3, 4, 5)
	fmt.Println(qun1)	//查看队列完整信息

	//获取队列数据
	data := qun1[0]
	fmt.Println(data)	//输出信息

	//删除此队列 output
	qun1 = qun1[1:]
	fmt.Println(qun1)	//查看队列完整信息
}

func add(){
	s := make([]int, 5)
	s1 := s
	//s = []int{1, 2, 3, 4, 5}
	fmt.Printf("切片s长度%v,地址%p\n", len(s), s)
	fmt.Printf("切片s1长度%v,地址%p\n", len(s1), s1)

	s = append(s, 23)
	//使用append追加元素后,原始切片数组地址也会发生改变。
	//当原始的地址发生改变后,已经和之前地址关联的切片,将不会和新切片地址保持引用关系。
	fmt.Printf("切片s长度%v,地址%p\n", len(s), s)
	fmt.Printf("切片s1长度%v,地址%p\n", len(s1), s1)

	//append不是依据追加的元素个数扩容的,而是依 据原切片的原始容量来计算。
	//扩容的算法大概是:若容量较小(小于1K)则成倍扩容,若容量较大(大于1k)则扩容特定长度。

}

输出:

[1 2 3 4 5 44 55 66 77]
切片s长度5,地址0xc0000ca060
切片s1长度5,地址0xc0000ca060
切片s长度6,地址0xc0000a60a0
切片s1长度5,地址0xc0000ca060
[1 2 3 4 5]
1
[2 3 4 5]
[1 2 3 4 5]
5
[1 2 3 4]

Process finished with exit code 0

指针

var i *int

一种存储内存地址的数据类型

package main

import "fmt"

func main() {
	num := 255
	fmt.Println("num 的内存地址位:", &num)
	//使用&关键词表达在内存中的地址

	var num_s  *int
	//声明一个int类型的指针变量num_s

	num_s = &num
	fmt.Printf("%v address: %v\n", num, num_s)

	fmt.Println("指针num_s的值为:", *num_s)
	//解引用使用*关键词表示

	*num_s++
	//解引用并自相加
	fmt.Println(num_s, num)

	p := &num_s
	//把一个整数型指针变量赋值到p

	fmt.Println(**p)
	//多级指针类型
	//整数型指针变量也是一个变量,也可以获取其内存地址到一个新的指针类型中,使用**即可解多级指针类型获取到源值

	// new 创建指针new(T) 指针类型T
	//new()实例化,会创建存储空间,并返回其地址。
	ap := new(int)
	ap = &num
	fmt.Println(ap)

	//空指针,没有指向内存地址的指针被称为空指针。使用nil表示
	var bp *int	//仅初始化,并没有赋值默认为零值nil
	fmt.Printf("%T\n%v", bp, bp)

}

输出:

num 的内存地址位: 0xc00000a0a0
255 address: 0xc00000a0a0
指针num_s的值为: 255
0xc00000a0a0 256
256
0xc00000a0a0
*int
<nil>
Process finished with exit code 0

结构体

type a_server stucr{}

##结构体 是一种自定义数据类型##

package main

import (
	"fmt"
)

func main() {
	type server struct {
		PlayerName string
		PlayerNum  int
		World      string
	}
	//定义一个server类型的结构体
	//type定义类型关键词
	//struct结构体关键词

	var s1_15 = server{
		PlayerName: "LIU_MC",
		PlayerNum:  1,
		World:      "DIM1",
	}
	//为server结构体赋值

	var c1_15 = server{
		"CCCP",
		2,
		"END",
	}
	//赋值如果不写成员变量名,必须按照定义顺序给全部成员变量一个初始值

	fmt.Println(s1_15, c1_15)

	fmt.Println(c1_15.PlayerName)
	//访问结构体成员变量使用点.关键符号 和访问包函数一样

	s3 := c1_15
	c1_15.PlayerName = "tcxjj"
	fmt.Println(c1_15.PlayerName, s3.PlayerName)
	//结构体是值类型,非引用类型,所以结构体的空值不是nil,而且当原结构体被更改后这个结构体不会变更数据

	temp := struct {
		name string
		amount int
	}{
		"南孚电池",
		6,
	}
	//没有名称的结构体,叫做匿名结构体
	//匿名结构体定义时必须初始化数据,匿名结构体一般用作临时数据
	fmt.Println(temp)
}

输出:

{LIU_MC 1 DIM1} {CCCP 2 END}
CCCP
tcxjj CCCP
{南孚电池 6}

Process finished with exit code 0


错误处理

err

一种存储错误信息的数据类型
实例演示:

package main
//错误处理
import "fmt"

func count(a, b float32, c string)(float32, error){
	var v float32
	switch c {
	case "+":
		v = a + b
	case "-":
		v = a - b
	case "*", "x", "X", "×":
		v = a * b
	case "/", "÷":
		if b <= 0  {
			return 0, fmt.Errorf("被除数不能为0或者小于0!%v", b)
		}else {
			v = a / b
		}
	case "%":
		v = float32(int(a) % int(b))
	case "&":
		v = float32(int(a) & int(b))
	case "|":
		v = float32(int(a) | int(b))
	case "^":
		v = float32(int(a) ^ int(b))
	case "<<", "<":
		v = float32(int(a) << int(b))
	case ">>", ">":
		v = float32(int(a) >> int(b))
	default:
		return 0, fmt.Errorf("未知的运算符%v!\n", c)
	}
	return v, nil
}

func main() {
	var (
		one float32
		two float32
		symbol string
	)
	for true {
		fmt.Println("输入第一个值")
		_, err := fmt.Scanln(&one)
		if err != nil {
			fmt.Printf("错误:%s", err)
			continue
		}
		fmt.Println("请输入运算符号(+加 -减 *乘 /除 %余 按位运算:&与 |或 ^异或 <<左移 >>右移)")
		_, err = fmt.Scanln(&symbol)
		if err != nil {
			fmt.Printf("错误:%s", err)
			continue
		}
		fmt.Println("输入第二个值")
		_, err = fmt.Scanln(&two)
		if err != nil {
			fmt.Printf("错误:%s", err)
			continue
		}

		value, err := count(one, two, symbol)
		if err != nil {
			fmt.Printf("错误:%v\n", err)
		} else {
			fmt.Printf("%v %v %v = %v\n", one, symbol, two, value)
		}
	}
}

输出:

输入第一个值
1
请输入运算符号(+加 -减 *乘 /除 %余 按位运算:&与 |或 ^异或 <<左移 >>右移)
+
输入第二个值
2
1 + 2 = 3
输入第一个值
/
错误:strconv.ParseFloat: parsing "": invalid syntax输入第一个值
错误:unexpected newline输入第一个值
1
请输入运算符号(+加 -减 *乘 /除 %余 按位运算:&与 |或 ^异或 <<左移 >>右移)
1
输入第二个值
1
错误:未知的运算符1!
# Go 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×