当前位置:网站首页>Golang 快速上手 (3)
Golang 快速上手 (3)
2022-06-23 09:56:00 【小狗吠吠吠】
目录
结构体
Golang 没有直接提供面向对象的概念,但是可以使用Go语法来实现面向对象编程的一些特性,例如:继承、多态、等特性。
定义一个结构体
type Animal struct {
Name string
Age int
}
初始化结构体
默认初始化
var dog Animal //定义一个结构体
使用键值对初始化
animal := Animal{
Name: "animal",
Age: 19,
}
列表初始化
必须初始化结构体的所有字段。
初始值的填充顺序必须与字段在结构体中的声明顺序一致。
该方式不能和键值初始化方式混用。
cat := Animal{
"cat",
12,
}
部分初始化
cat := Animal{
Name: "cat",
}
结构体的指针
new 关键字创建结构体指针
pa := new(Animal)
fmt.Printf("pa: %T\n", pa) //pa: *main.Animal
访问结构体成员
指针和对象都可以通过逗号访问结构体对象的成员,如果指针通过逗号访问成员编译器会默认解引用,(*pa),name 等价于 pa.name
pa := new(Animal)
pa.Name = "fish"
pa.Age = 3
(*pa).Name = "dog"
(*pa).Age = 4
fmt.Printf("pa: %v\n", *pa) //pa: {dog 4}
结构体的访问权限
结构体名称首字母大写,那么在其他包内才可以定义Person对象,小写则无法访问。
并且,结构体的属性首字母大写则其访问权限为public的,若为小写,则为private
type Person struct {
Name string
Age int
}
func main() {
p1 := Person{
Name: "marry",
Age: 30,
}
fmt.Printf("p1.Name: %v\n", p1.Name)
fmt.Printf("p1.Age: %v\n", p1.Age)
}
编译器报错
type Person struct {
name string
age int
}
func main() {
p1 := Person{
name: "marry",
age: 30,
}
//p1.Name undefined (type Person has no field or method Name, but does have name)
fmt.Printf("p1.Name: %v\n", p1.Name)
fmt.Printf("p1.Age: %v\n", p1.Age)
}
方法首字母大写才能在其他包内访问
type Person struct {
name string
age int
}
func (p Person) Run() {
fmt.Println("Person Run")
}
func main() {
p1 := Person{
name: "marry",
age: 30,
}
}
对象的方法
Golang 没有直接提供面向对象的特性,也没有类对象的概念。但是,可以使用结构体来模拟这些特性。
定义结构体方法
Golang 中的方法,是一种特殊的函数,定义于struct之上(与struct关联、绑定),被称为struct的接受者(receiver)。
type Animal struct {
Name string
Age int
}
func (a Animal) Eat() {
fmt.Println("Animal Eat")
}
func (a Animal) Sleep() {
fmt.Println("Animal Sleep")
}
func main() {
a := Animal{
Name: "dog",
Age: 10,
}
a.Eat()
a.Sleep()
}
方法接收者类型
//传递指针才能改变其值
func (per *Animal) Set1(age_ int, name_ string) {
per.age = age_
per.name = name_
}
//值传递 内部修改不会影响外部
func (per Animal) Set2() (int, string) {
per.age = age_
per.name = name_
}
方法注意点
方法的receiver type可以是其他类型,如:type定义的类型别名、slice、 map、 channel、 func类型等
struct 结合它的方法就等价于面向对象中的类。只不过struct可以和它的方法分开,,并非一定要属于同一个文件,但必须属于同一个包。
方法有两种接收类型: (T Type) 和(T *Type) , (T Type)是值传递,(T *Type)传递指针,内部修改会影响实参。
方法就是函数,,Go中没有方法重载(overload)的说法,也就是说同一个类型中的所有方法名必须都唯一。
如果receiver是一个指针类型, 则会自动解除引用。
方法和type是分开的,意味着实例的行为(behavior)和数据存储(field)是分开的,但是它们通过receiver建立关联关系。
接口
go语言的接口,是一种新的类型定义,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
语法格式和方法非常类似。
定义一个接口
type Displayer interface {
DisplayAudio(string)
Displayvideo(string)
}
实现接口
type Displayer interface {
DisplayAudio()
DisplayVideo()
}
type MP4 struct {
}
func (mp4 MP4) DisplayAudio() {
fmt.Println("DisplayAudio")
}
func (mp4 MP4) DisplayVideo() {
fmt.Println("DisplayVideo")
}
func main() {
var player Displayer = MP4{
}
player.DisplayAudio()
player.DisplayVideo()
}
要注意,实现接口必须实现接口中的所有方法,不然无法将结构体赋值给接口类型变量
值类型receiver 指针类型receiver
和方法传参一样,必须传递指针才能在内部修改其值。。
接口和struct
一个结构体可以实现多个接口
多个结构体实现同一个接口(实现多态)
一个结构体实现多个接口
type Displayer interface {
DisplayAudio()
DisplayVideo()
}
type PlayGamer interface {
PlayGame()
}
type MP4 struct {
Volume int
}
func (mp4 MP4) DisplayAudio() {
fmt.Println("DisplayAudio")
}
func (mp4 MP4) DisplayVideo() {
fmt.Println("DisplayVideo")
}
func (mp4 MP4) PlayGame() {
fmt.Println("PlayGame")
}
func main() {
var player1 Displayer = MP4{
Volume: 10,
}
var player2 PlayGamer = MP4{
Volume: 10,
}
player1.DisplayAudio()
player1.DisplayVideo()
player2.PlayGame()
}
实现多态
多个结构体实现同一个接口 (多态)
package main
import "fmt"
type Per interface {
eat()
sleep()
}
type Dog struct {
}
type Cat struct {
}
func (d Dog) eat() {
fmt.Println("Dog eat")
}
func (d Dog) sleep() {
fmt.Println("Dog eat")
}
func (d Cat) eat() {
fmt.Println("Cat eat")
}
func (d Cat) sleep() {
fmt.Println("Cat eat")
}
type Person struct {
}
func (p Person) care(per Per) {
per.eat()
per.sleep()
}
//其实就是多态的使用
//OCP 开放扩展 关闭修改
func main() {
dog := Dog{
}
cat := Cat{
}
person := Person{
}
person.care(dog)
person.care(cat)
}
简单地实现一个多态的案例,传递Dog对象调用的就是Dog类的方法,传递Cat对象调用Cat类的方法。
继承
定义一个父类
type Animal struct {
Name string
Age int
}
func (a Animal) Sleep() {
fmt.Println("Animal Sleep")
}
func (a Animal) Eat() {
fmt.Println("Animal Eat")
}
子类可以重定义父类的方法
type Dog struct {
Animal
}
func (d Dog) Eat() {
fmt.Println("Dog Eat")
}
func main() {
d1 := Dog{
Animal: Animal{
Name: "Dog",
Age: 3,
},
}
d1.Eat() //Dog Eat
}
Golang 构造函数
golang没有构造函数的概念,但可以使用函数来模拟构造函数的的功能。
type Student struct {
Name string
Age int
}
func NewStudent(name string, age int) (*Student, error) {
if age > 99 || age < 0 {
return nil, fmt.Errorf("age input error")
}
return &Student{
Name: name, Age: age}, nil
}
Golang 包

包可以区分命令空间(一个文件夹中不能有两个同名文件),也可以更好的管理项目。go中创建一个包,一般是创建一个文件夹, 在该文件夹里面的go文件中,使用package关键字声明包名称,通常,文件夹名称和包名称相同。并且同一个文件下面只有一个包
包的注意点:
一个文件夹下只能有一个package
- import后面的其实是GOPATH开始的相对目录路径,包括最后一段。但由于一个目录下只能有一个package,所以import 一个路径就等于是import了这个路径下的包。
需要注意,这里指的是“直接包含”的go文件。 如果有子目录,那么子目录的父目录是完全两个包。
比如实现了一个计算器package,名叫calc,位于calc目录下。但又想给别人一个使用范例,于是在calc下可以建个example子目录(calc/example/) ,这个子目录里有个example.go (calc/example/example.go) 。此时,example.go可以是main包,里面还可以有个main函数。
- 一个package的文件不能在多个文件夹下
如果多个文件夹下有重名的package,它们其实是彼此无关的package。
如果一个go文件需要同时使用不同目录下的同名package,需要在import这些目录时为每个目录指定一个package的别名。|
包的导入方式
匿名导入
包一但导入就必须使用其内部函数,如未使用编译器报错,但如果有一个需求,需要调用 test_lib 的init函数,又不用调用test_lib内的函数就可以用 _ 匿名导入包。
import (
"fmt"
_ "test_lib"
)
重命名包:
如果包的名称太长,可以对其重命名使用。
import (
"fmt"
my_lib "test_lib"
)
func main() {
my_lib.API()
}
展开包:
test_lib 包名前加逗号,那么调用test_lib 内的函数可以不加上包名,就像函数定义在当前包一样使用。
import (
"fmt"
. "test_lib"
)
func main() {
API() // test_lib.API() 直接调用
}
不推荐使用,如果两个包都使用逗号展开包,如果两个包内存在同名函数就无法区分。
包管理工具 module
go modules 是golang 1.11新加的特性,用来管理模块中包的依赖关系。
常用指令
初始化模块
go mod init <项目模块名称>
依赖关系处理,根据go.mod文件
go mod tidy
将依赖包复制到项目下的vendor目录。
如果无法科学上网,可以使用这个命令,随后使用go build -mod=vendor编译
go mod vendor
显示依赖关系
go list -m all
显示详细依赖关系
go list -m -json all
下载依赖 ([[email protected]] 不是必写的)
go mod download [[email protected]]

边栏推荐
- mysql乐观锁与悲观锁
- Notes on using the coding code base
- Year end answer sheet! Tencent cloud intelligent comprehensive strength ranks first in China!
- [plugin:vite:import-analysis]Failed to resolve import “@/“ from ““.Does the file exist
- 必须知道的RPC内核细节(值得收藏)!!!
- Bugs encountered in Oracle
- NiO example
- Dr. Sun Jian was commemorated at the CVPR conference. The best student thesis was awarded to Tongji Ali. Lifeifei won the huangxutao Memorial Award
- Unity技术手册 - 生命周期内速度限制(Limit Velocity Over Lifetime)子模块和速度继承(Inherit Velocity)子模块
- Install using snap in opencloudos NET 6
猜你喜欢

Go string comparison

Bioinformatics | 基于相互作用神经网络的有效药物-靶标关联预测

SQL教程之SQL 中数据透视表的不同方法

ICLR 2022 | dynamic convolution tadaconv in video and efficient convolution video understanding model tadaconvnext

Alimentation des animaux de compagnie basée sur stm32

Dr. Sun Jian was commemorated at the CVPR conference. The best student thesis was awarded to Tongji Ali. Lifeifei won the huangxutao Memorial Award

Gorm advanced query

J. Med. Chem. | RELATION: 一种基于靶标结构的深度学习全新药物设计模型

Copilot免费时代结束!正式版67元/月,学生党和热门开源项目维护者可白嫖

Mysql database introduction summary
随机推荐
Shengshihaotong enables high-quality development with industrial Digitalization
oracle中遇到的bug
Bioinformatics | 基于相互作用神经网络的有效药物-靶标关联预测
#gStore-weekly | gStore源码解析(四):安全机制之黑白名单配置解析
MySQL optimistic lock and pessimistic lock
mysql innodb 的 redo log buffer 中未 commit 的事务持久化到 redo log 后,万一事务 rollback 了怎么办?redo log 怎么处理这个事务操作?
快速排序的简单理解
AI system frontier dynamics issue 38: Google has abandoned tensorflow?; Four GPU parallel strategies for training large models; Father of llvm: modular design determines AI future
STM32F1与STM32CubeIDE编程实例-红外寻迹传感器驱动
在OpenCloudOS使用snap安装.NET 6
Dr. Sun Jian was commemorated at the CVPR conference. The best student thesis was awarded to Tongji Ali. Lifeifei won the huangxutao Memorial Award
Subscript operator of map
Go language JSON processing
Distributed common interview questions
Unable to enter the system normally, press F8 to select other items to try to enter
用贪吃蛇小游戏表白(附源码)
2021-05-07构造器
2021-05-10方法重写多态注意事项
High performance computing center Infiniband overview
Install using snap in opencloudos NET 6