今日小结算
文章目录
一、学了什么
1. Go基础:
一个报错
这个错误通常发生在尝试为来自其他包的类型定义方法时。在Go语言中,你不能为不属于当前包的类型添加方法(接收器方法)。
方案1:使用组合包装类型 定义一个新的结构体类型,将之前的类型作为他的一部分。然后再添加方法,对其进行操作
方案2:在原始包中定义方法
方案3:使用函数替代方法
为什么Go有这样的限制?
Go语言设计这个限制有几个原因:
封装性:防止外部包修改或扩展其他包的类型行为
明确性:类型的方法集在定义它的包中明确指定
维护性:避免"猴子补丁"式的代码修改
1. 结构体、方法、指针
- 结构体:定义、初始化、赋值、
- 方法: 方法关联结构体、指针接收器和值接收器、返回值和返回指针
2.组合、转发
- 组合:简单说就是结构体的嵌套,提前定义个一个结构体A,作为结构体B中的字段类型。A结构体获得了B结构体的属性和方法
type A struct{
Id int
Age int
}
type B struct {
Name string
Atype A
}
func main() {
aa := A{Id:100, age:18}
bb := {Name:"bb",Atype:aa}
fmt.println(bb.name,bb.Id,bb.Age)
fmt.println(bb.name,bb.Id,bb.Age)
}
- 转发:嵌入类型时不给字段名,外部类型自动获得了嵌入类型的方法和属性,这些方法会被"转发"到嵌入类型上
组合两种用法:
1. 方法和A结构体关联,A结构体在B中,不给定字段值,直接用。B.func()
2. 方法和A结构体关联,A结构体在B中,给定字段值,间接用。B.A.func()
type Student struct{
Name string
Id int
}
func (w Student) Write(data []byte) (int, error) {
fmt.Println("Writing data:", string(data))
return len(data), nil
}
type LogWriter struct {
code string
Student // 嵌入Student类型
}
func main() {
stu := Student{Name:"ss",Id:100}
lw := LogWriter{code:"test",Student:stu}
lw.Write([]byte("hello")) // Write类型的方法被转发到lw类型上,他也可以直接用
lw.Student.Write([]byte("hello")) //或者也可以先引用Write,再用Write()方法
//访问Student属性
fmt.println(lw.Student.Name)
fmt.println(lw.Name) // lw自动继承了student的属性Name
}
3. 指针
和c++类似
4. 接口
接口可以和结构体的嵌入特性一起使用
package main
import "fmt"
2. 并发
1. goroutine
2. 通道
3. select
4. 阻塞和死锁
5 并发
共享值
竞争条件
互斥锁
3. go-zero
1. 一个test demo
流程:
- 编写
test.api
syntax = "v1"
//定义 type
type LoginReq {
Id string `json:"Id"`
}
type LoginStatus {
code string `json:"code"`
}
// 定义service
service test {
@handler login //login中间件
post /user/login (LoginReq) returns (LoginStatus) //post 方法 路径 接受参数类型 返回参数类型
@handler getUser // getUser 中间件
get /user/:id returns (UserInfo) // get方法 路径 返回类型
}
- 生产模板↓
goctl api go --api ./test.api -d ./ --style=go_zero
- 修改
logic
目录中的具体业务逻辑 - go run test.go
二、做了什么
1. http调试方案
a. 本打算下载potman,忙活了半天。中文版只有旧版本,于是选择了apifox
b. 由于mac和机械革命的电脑路由地址不同。为方便调试,在两边的hosts文件中都加了条域名解析
如mac中的/etc/hosts
文件为:
127.0.0.1 lanmac
192.168.2.3 lanvpx #机械革命电脑的局域网地址
机械革命中的hosts
文件为
192.168.2.4 lanmac
127.0.0.1 lanvpx
如此一来,在两台不同机器中对服务器进行测试时,不需要修改脚本中的ip地址,直接使用lanmac
和lanvpx
即可
2.
三、遇到的问题
1. doker环境配置问题【已解决】
2. ssh连接docker后无法使用go、goctl等工具【未解决】
问题描述
如标题,ssh连接时我无法使用go、goctl等命令:
而直接进入容器中使用,环境有效,如图go、goctl等都可以正常使用:
问题分析
似乎是环境变量失效
如图,直接连接docker时,环境变量中有go
而ssh连接时,没有go
问题原因
导致环境变量失效的原因?
bash的四种模式
模式 | 交互式? | 登录Shell? | 配置文件加载顺序 | 典型场景 |
---|---|---|---|---|
交互式登录Shell | ✅ 是 | ✅ 是 | 1. /etc/profile 2. ~/.bash_profile → ~/.bash_login → ~/.profile 3. 退出时加载 ~/.bash_logout | -SSH登录-本地终端登录-su - username |
交互式非登录Shell | ✅ 是 | ❌ 否 | 1. ~/.bashrc | - 图形界面打开终端- 已登录后执行 bash- su username(不带 -) |
非交互式登录Shell | ❌ 否 | ✅ 是 | 1. /etc/profile 2.~/.bash_profile → ~/.bash_login → ~/.profile | - ssh server ‘command’- 特殊配置的脚本环境 |
非交互式非登录Shell | ❌ 否 | ❌ 否 | 默认不加载任何配置文件(除非脚本中显式 source 或设置了 BASH_ENV 变量) | - 执行脚本 ./script.sh- bash -c “command” |
差异总结
-
交互性
-
交互式模式:显示提示符,用户可输入命令(通过 $- 包含 i 判断)
-
非交互式模式:通常用于执行脚本或单条命令
-
-
登录属性
-
登录Shell:会加载系统级配置(/etc/profile)和用户级登录配置(~/.bash_profile 等)
-
非登录Shell:仅加载 ~/.bashrc(交互式)或不加载配置(非交互式)
-
-
配置文件优先级
-
登录Shell优先检查 ~/.bash_profile,若不存在则尝试 ~/.bash_login 和 ~/.profile
-
非登录Shell完全依赖 ~/.bashrc
-
-
典型问题
-
环境变量失效:通常因为脚本以非交互式非登录模式运行,未加载预期配置文件
-
别名/函数无效:可能因为配置写在了 ~/.bashrc 但当前是登录Shell(未主动加载 ~/.bashrc)
由此分析,是由于加载配置文件顺序不同。ssh登录时优先加载profie中的配置,而在docker容器中,profile中并没有配置文件,因此环境变量失效
-
问题解决 【暂未完全解决】
修改/etc/profile文件
export $(cat /proc/1/environ |tr '\0' '\n' | xargs)
使其生效
source /etc/profile
问题
提示-w
参数。很奇怪
观察我的profile文件,发现我的环境变量中有这么一条
推测时export
时,将此处解析为了一个参数。于是分开export
即可
先echo
出环境变量,跳过代理的那一段。复制下来,分别export
export PATH=/go/bin:/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=83c142424f11 TERM=xterm TZ=Asia/Shanghai GOLANG_VERSION=1.24.2 GOTOOLCHAIN=local
export HOME=/root
测试
执行后再次测试go、goctl。此时已经可以正常使用
但是这样有点麻烦,难道我每次ssh之后都要export
一下吗?
下次写个脚本,在ssh后自动执行一次
3. 使用Goland或者vscode连接docker容器进行开发【未解决】
考虑方案
- vscode中使用远程开发 【不可用】
由于ssh连接后go、goctl等命令不可用,于是放弃 - golang直接连接开发 【不可用】
- 选择docker->dockerfile
gozero项目中使用的dockerfile是一堆,而这里要选择具体的某一个,不知如何解决。 - 构建中选择docker构建
不知如何选择,都尝试了一下。起不来
- 选择docker->dockerfile