安装 与 配置
- 访问 go.dev/ ,点击 Download ,下载对应平台安装包,安装即可
- 如果无法访问上述网址,可以改为访问 studygolang.com/dl 下载安装
- 如果访问 github 速度比较慢,建议配置
go mod proxy,参考 goproxy.cn/ 里面的描述配置,下载第三方依赖包的速度可以大大加快
vscode居然下载文件在这 go.lnk
学习 Go 语言基础语法
空余时间阅读 Go语言圣经(中文版)
还是菜鸟靠谱
构造体
type Books struct {
title string
author string
subject string
book_id int
}
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
Book2.title = "Python 教程"
参数
- 传值
printBook(Book2)
func printBook( book Books ) {
fmt.Printf(book.title="change")
}
- 传引用
printBook(&Book2)
func printBook( book *Books ) {
fmt.Printf(book.title="change")
}
定义方法
type rect struct {
width, height int
}
//构造体的方法
//r 相当于this
//*rect 表示使用*rect类型调用该方法
func (r *rect) area() int {
r.height = 6
return r.width * r.height
}
//构造体的方法,r相当于调用构造体的复制
func (r rect) perim() int {
r.width = 9
return 2*r.width + 2*r.height
}
r := rect{width: 10, height: 5}
area := r.area() // 使用指针接收器调用方法,没有显式使用指针,但是 Go 会自动处理
perim := r.perim() // 使用值接收器调用方法
fmt.Println(r)
接口
-
接口
需要实现
area() float64
type Shape interface {
area() float64
}
- 实现结构1
隐式实现:如果一个类型实现了一个接口定义的所有方法,那么它就自动地实现了该接口
type Rectangle struct {
width float64
height float64
}
//值调用
func (r Rectangle) area() float64 {
return r.width * r.height
}
- 实现结构2
type Circle struct {
radius float64
}
//指针调用
func (c *Circle) area() float64 {
return 3.14 * c.radius * c.radius
}
- 通过将接口作为参数来实现对不同类型的调用,从而实现多态
- 接口类型变量可以存储任何实现了该接口的类型的值
func main() {
var s Shape
s = Rectangle{width: 10, height: 5}
fmt.Printf("矩形面积: %f\n", s.area())
s = &Circle{radius: 3}
fmt.Printf("圆形面积: %f\n", s.area())
}
Shape接口的area方法必须使用值接收器实现接口的构造体使用 值调用
s = Rectangle{width: 10, height: 5} s.area()实现接口的构造体要是 指针调用
s = &Circle{radius: 3} //表明s 为指针类型 s.area()
新建
单文件
同一个包下:
- 方法和全局变量可以直接使用
不同包:
- 需要
包名.方法()调用不过嘛只有一个文件在main包下且只有一个main方法
创建 hello.go
//myhellogo\hello.go
package main //与文件夹名无关
import "fmt" //导包时,不同包下要加 包名
func main() {//一个文件夹下只有一个main
fmt.Println("Hello, World!")
}
go run hello.go
go build hello.go
//如果是普通包(非main包), 只做检查, 不产生可执行文件
//如果是main包,生成可执行文件, 默认生成的可执行文件名为项目名(go mod里面)
新建项目
go env 命令 可以看到 GO111MODULE 字段
-
auto 如果在gopath/src下,但是存在go.mod文件,就采用的go mod包管理方式; 在gopath/src下,但没有go.mod文件, 采用以前默认的方式; 若未在gopath/src下, 自然是采用的go mod包管理方式(前提是需要go.mod文件存在)
-
on
不管在不在gopath/src下,都采用的go mod包管理方式
-
off
就是以前的默认方式(这时候项目必须放在gopath/src下),若需要引用外部包文件,使用go get命令下载下来。 比如在一个.go文件中,require (“github.com/gin-gonic/gin”) 那么使用go get github.com/gin-gonic/gin ,并且这个下载下来的资源会放在gopath/src下, 而使用go mod包管理的方式,下载下来的资源会放在gopath/pkg下,后边会用测试案例详细介绍如何操作。
gopath/src 管理
旧写法的项目一定要放在这里
package util
import("fmt")
func Test() { //注意首字母大写, 不然无法调用,大写表示允许被调用
fmt.Println("I'm pkg/util/Test()")
}
package main
import("demo1/pkg/util")
func main() {
util.Test()
}
这里主要分析import(“demo1/pkg/util”) , 对于以前的默认方式,也就是项目必须放到gopath/src下的原因, 其实它会在demo1/pkg/util前面自动加上gopath/src路径, 完整的写出来其实是gopath/src/demo1/pkg/util, 这也就是为什么必须放到gopath/src下。
go mod 管理
go mod init demo:生成,这就相当于命名空间了,其他同项目下的文件都可以使用import demo来导该项目的包
module demo
go 1.20
package main
import (
"demo/util"
)
func main() {
util.Test()
}
package util
import (
"fmt"
)
func Test() { //注意首字母大写, 不然无法调用,大写表示允许被调用
fmt.Println("I'm pkg/util/Test()")
}
demo用来替代了当下的绝对路径,在这里其实demo表示的是当前项目路径, 所以它并不依赖gopath/src, 你将项目移到其他位置, demo就会表示那个位置的绝对路径, demo可以换成任意字符, 比如你最开始用的是go mod init demo, 那么这里就要 import(“demo/pkg/util”), 可以在go.mod文件中对它(demo名称)进行修改。
其他:
-
同一个文件夹下的包名要一致
-
文件夹名称最好和包名一致
- 不然有点麻烦
引用github上的包
-
go mod 访问联网包会下载到path
- 使用
go get github.com/gin-gonic/gin, 然后这个资源会下载到gopath/src中 - 或者:go mod tidy 下载所有
- 使用
-
go mod 外部项目包可以重定向,比如
-
导包:
import("github.com/cnwyt/my_gotest/pkg/util") -
.mod文件:
require github.com/cnwyt/my_gotest v0.0.0replace github.com/cnwyt/my_gotest => C://my_gotest//这就是replace的用处,用于替换
-