GO语言基础

一、基本操作

小tip

变量
  1. :=
    :=为短变量声明,只能用于函数内
Println与Printf

Println里不能出现%s %d之类的,但可以直接打印字符串,如:

fmt.Println("numbers ==", numbers)
匿名函数

使用场景:

  1. 由于函数内部无法申明函数,因此使用先声明函数,再使用函数
func main() {
   f1 := func(x, y int) {
   	fmt.Println(x + y)
   }
   f1(10, 20)
}
  1. 立即执行函数。
func main() {
	func (x,y int)  {
		fmt.Println(x+y)
	}(100,300) //马上就传参数
}

切片

  1. Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
数组初始化:
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
//字面量方式:
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
切片初始化
var identifier []type
//字面量
s :=[] int {1,2,3 } 
//make方式
slice1 := make([]type, len) 
//可指定容量:make([]T, length, capacity)
s :=make([]int,len,cap) 

切片的规则:(和Python的字符串基本一样)

如:

len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]

append和copy函数

var numbers []int //空切片
  /* 向切片添加一个元素 */
 numbers = append(numbers, 1)
 
   /* 同时添加多个元素 */
   numbers = append(numbers, 2,3,4)

 /* 拷贝 numbers 的内容到 numbers1 */
   copy(numbers1,numbers) 

3.集合

定义:

/* 使用map关键字声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)

使用range访问map:得到的是key。

判断是否key存在:

/* 创建map */
countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}
capital, ok := countryCapitalMap["India"] /*如果确定是真实的,则存在,否则不存在 */
fmt.Println(capital)                      //若不存在,则为空;若存在返回value
fmt.Println(ok)  //true  or false

删除集合元素:delete()

delete(countryCapitalMap, "France")

defer

应用场景:多用于资源释放

  • 把defer后面的语句延迟到函数即将返回的时候再执行。
  • 若有多个defer,则按照栈的结构,先进后出执行defer的内容。

defer执行时机:
return分为两步:赋值和真正返回指令
在这里插入图片描述

package main
import "fmt"
func f1() int {
	x := 5
	defer func() {
		x++ //修改的是x不是返回值
	}()
	return x
}
func f2() (x int) {
	defer func() {
		x++ //
	}()
	return 5
}
func f3() (y int) {
	x := 5
	defer func() {
		x++
	}()
	return x //返回值=y=x=5
}
func f4() (x int) {
	defer func(x int) {
		x++
	}(x)
	return 5
}
func main() {
	fmt.Println(f1())
	fmt.Println(f2())
	fmt.Println(f3())
	fmt.Println(f4())
}
//执行结果:
5
6
5
5

GO语言接口

接口:一种数据类型。

panic

package main

import "fmt"

func f1() {
	fmt.Println("A")
}
func f2() {
	defer func() {
		fmt.Println("出错了,后面不执行了...")
	}() //defer一定要在panic申明之前定义
	panic("有错,终止...")
	fmt.Println("我会被执行吗") //不会
}
func f3() {
	fmt.Println("看看我..")
}
func main() {
	f1()
	f2()
	f3()
}

自定义类型和类型别名

type myint int //自定义类型
type yourint=int //类型别名

自定义类型永久的将数据类型改成自己定义的了,但类型别名本质还是原本的数据类型。

结构体

//基本形式
type person struct {
	name, city string
	age        int8
}

func main() {
	//实例化
	var p1 person
	p1.name = "Chongqing"
	p1.age = 19
	fmt.Printf("p1=%v\n", p1) //p1={Chongqing  19}
	fmt.Printf("p1=%#v\n", p1)//p1=main.person{name:"Chongqing", city:"", age:19}
}

new创建指针类型结构体

var p2 = new(person)
fmt.Printf("%T\n", p2)     //*main.person 一个结构体指针
fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"", city:"", age:0}
//下面写法等价于用new
p3 := &person{}

注:空结构体是不占用空间的。

为结构体创建方法:

func (p person) speak(){
	fmt.Println("嘿嘿嘿")
}

method与receiver

receiver的概念就类似于其他语言中的this或者 self。

//定义
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
    函数体
}
// 使用值接收者
func (p Person) SetAge2(newAge int8) {
	p.age = newAge
}
// 使用指针接收者
func (p *Person) SetAge(newAge int8) {
	p.age = newAge
}

什么时候应该使用指针类型接收者

  1. 需要修改接收者中的值
  2. 保证一致性,如果有某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者。

结构体中字段大写开头表示可公开访问,小写表示私有(仅在定义当前结构体的包中可访问)。

包的用法

  1. 一个包可以简单理解为一个存放.go文件的文件夹。该文件夹下面的所有.go文件都要在非注释的第一行添加如下声明,声明该文件归属的包。
package name //可以不和文件夹的名称相同
  1. 包名为main的包是应用程序的入口包,这种包编译后会得到一个可执行文件,而编译不包含main包的源代码则不会得到可执行文件。

标识符可见性

在Go语言中是通过标识符的首字母大/小写来控制标识符的对外可见(public)/不可见(private)的。在一个包内部只有首字母大写的标识符才是对外可见的。(包括变量和函数名都是只有大写可以被外部访问)

init函数
  1. 不接收任何参数也没有任何返回值
  2. 当程序启动的时候,init函数会按照它们声明的顺序自动执行。
  3. 每一个包初始化的时候都是先执行依赖的包中声明的init函数再执行当前包中声明的init函数。

GO module

在这里插入图片描述

接口

  1. 是一个类型
    在这里插入图片描述
//定义
type speaker interface{
	speak()  //只要用speak()方法的对象和类型,都可看做是speaker类型。
}
//写函数
func sp(obj speaker){
	obj.speak() //接收的x是一个接口,不用管他到底是什么类型,执行x的speak方法
}
//调用
func main(){
	var p person
	p.name="niu"
	sp(p) //等价于执行了p.speak(). sp函数可以传任意有speak方法的类型
	//法二 先定义一个接口类型变量
	var s1 speaker
	p1:=person{
		name:"cat"
	}
	s1=p1
	sp(s1) //调用
}

注意,一种类型的方法需要有所有interface中的方法


值接收者实现接口

**还可以使用指针接收实现接口的方法:**只需要在接口对应的函数方法接收参数处,加个*即可

类型与接口关系
多个类型对应一个接口
  1. 先定义多接口
// Mover 接口
type Mover interface {
	Move()
}
  1. 定义
type Dog struct {
	Name string
}
// 实现Mover接口
func (d Dog) Move() {
	fmt.Printf("%s会动\n", d.Name)
}
// Car 汽车结构体类型
type Car struct {
	Brand string
}
// Move Car类型实现Mover接口
func (c Car) Move() {
	fmt.Printf("%s速度70迈\n", c.Brand)
}
  1. 调用接口
var obj Mover

obj = Dog{Name: "旺财"}
obj.Move()

obj = Car{Brand: "宝马"}
obj.Move()
空接口

空接口是指没有定义任何方法的接口类型,空接口类型的变量可以存储任意类型的值。

// Any 不包含任何方法的空接口类型
type Any interface{}
//或者:
var x interface{}  // 声明一个空接口类型变量x

作用

  • 空接口作为函数的参数,接收任意类型的函数参数。
// 空接口作为函数参数
func show(a interface{}) {
	fmt.Printf("type:%T value:%v\n", a, a)
}
  • 使用空接口实现可以保存任意值的字典。(不用事先声明)
// 空接口作为map值
	var studentInfo = make(map[string]interface{})
	studentInfo["name"] = "沙河娜扎"
	studentInfo["age"] = 18
	studentInfo["married"] = false
	fmt.Println(studentInfo)
接口值

在这里插入图片描述

类型断言

该语法返回两个参数,第一个参数是x转化为T类型后的变量,第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败

var n Mover = &Dog{Name: "旺财"}
v, ok := n.(*Dog) //看这里的用法
if ok {
	fmt.Println("类型断言成功")
	v.Name = "富贵" // 变量v是*Dog类型
} else {
	fmt.Println("类型断言失败")
}

error接口

1、基本定义类型

Go 语言中使用一个名为 error 接口来表示错误类型。默认零值为nil

type error interface {
    Error() string
}

error 接口只包含一个方法——Error,这个函数需要返回一个描述错误信息的字符串。通常将调用函数返回的错误与nil进行比较,以此来判断函数是否返回错误。如:

file, err := os.Open("./xx.go")
if err != nil {
	fmt.Println("打开文件失败,err:", err)
	return
}
二、自定义错误
  1. 使用errors包提供的New函数:errors.New
  2. 定义一个错误变量
var EOF = errors.New("EOF")
  1. 用于函数返回
func queryById(id int64) (*Info, error) {
   if id <= 0 {
   	return nil, errors.New("无效的id")
   }
}

time包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值