GoLang记录
goroute、select、channel练习
请写出一个场景:二营长的意大利炮
为了高效的打鬼子,二营长搬出了他珍藏的一门意大利炮,并命令一堆手下来操作意大利炮
- 发射一下意大利炮需要经过三个步骤:
装填
→瞄准
→发射
- 每个阶段打印出这个阶段的名称即可
- 每一个手下都是一个 goroutine
- 需要使用 channel 来同步各个手下的操作
- 作为指挥的二营长,他希望一个命令就可以停止打炮
- 按下
q
就停止打炮了,kill 进程不算
- 可以使用
"github.com/eiannone/keyboard"
来监听键盘按键事件
package main
import ( "fmt" "github.com/eiannone/keyboard" "time" )
func main() { var ( // 创建用于同步的通道 aim = make(chan struct{}) load = make(chan struct{}) launch = make(chan struct{}) stop = make(chan struct{}) )
go handleLoad(load, aim, stop) go handleAim(aim, launch, stop) go handleLaunch(launch, stop)
go listenQuit(stop)
// 空结构体通常用于在 goroutine 之间传递信号,适用于只需要信号不需要数据的场景 load <- struct{}{}
// 监听多个信道 select { case <-launch: fmt.Println("任务完成!") case <-stop: fmt.Println("停止打炮!") } }
func handleAim(load chan struct{}, aim chan struct{}, stop chan struct{}) { select { case <-load: fmt.Println("正在瞄准!") time.Sleep(5 * time.Second) aim <- struct{}{} case <-stop: } }
func handleLoad(aim chan struct{}, launch chan struct{}, stop chan struct{}) { select { case <-aim: fmt.Println("正在装填!") time.Sleep(10 * time.Second) launch <- struct{}{}
case <-stop: } }
func handleLaunch(launch chan struct{}, stop chan struct{}) { select { case <-launch: fmt.Println("发射!") case <-stop: } }
func listenQuit(stop chan struct{}) { defer keyboard.Close() if err := keyboard.Open(); err != nil { fmt.Println("Failed to open keyboard!", err) return }
for { char, _, err := keyboard.GetSingleKey() if err != nil { fmt.Println("Failed to read keyboard input!") continue } if char == 'q' || char == 'Q' { close(stop) break } } }
|
结构体练习
package main
import "fmt"
type Movie struct { Name string Director string Time string Score float64 UserRate []float64 }
func (m *Movie) AddUserRate(rate float64) { m.UserRate = append(m.UserRate, rate) }
func main() { a := Movie{Name: "西线无战事", Director: "爱德华·贝尔格", Time: "148 minutes", Score: 8.8, } fmt.Printf("请输入你的命令:\n1.获得名字\n2.获得导演名\n3.获得片长\n4.获得评分\n5.用户评分\n6.退出程序\n") var option int for { fmt.Scanf("%d ", &option) switch option { case 1: fmt.Println(a.Name) case 2: fmt.Println(a.Director) case 3: fmt.Println(a.Time) case 4: if len(a.UserRate) == 0 { fmt.Println("暂无评分!") } else { for i, rate := range a.UserRate { fmt.Printf("用户 %d 评分: %.1f\n", i+1, rate) } } case 5: var rate float64 fmt.Println("请输入评分(0-10.0):") fmt.Scanln(&rate) if rate < 0 || rate > 10 { fmt.Println("无效评分!请重新输入。") } else { a.AddUserRate(rate) fmt.Println("评分已添加!") } case 6: return default: fmt.Println("无效的选项,请重新输入。") } fmt.Printf("\n请输入你的命令:\n1.获得名字\n2.获得导演名\n3.获得片长\n4.获得评分\n5.用户评分\n6.退出程序\n") } }
|
database/mysql连接数据库
import ( "database/sql" //标准库 _ "github.com/go-sql-driver/mysql" //我们使用的mysql,需要导入相应驱动包,否则会报错 "log" )
var db *sql.DB
func InitDB() { var err error // 设置一下dns charset:编码方式 parseTime:是否解析time类型 loc:时区 dsn := "root:123456@tcp(192.168.10.104:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local" // 打开mysql驱动 db, err = sql.Open("mysql", dsn) if err != nil { log.Fatalln(err) } // 尝试与数据库建立连接(校验dsn是否正确) err = db.Ping() if err != nil { log.Fatalln(err) } log.Println("DB connect success") return }
|
目录规范
------------------------- go目录 ---------------------------- /cmd:项目的可执行文件名称相符,通常有一个简短的main函数。从/internal和/pkg目录导入代码。其他没有了 /internal: 私有应用程序和库代码 /pkg:外部应用可以导入的库代码 /vendor:应用程序依赖项 -----------------服务应用程序目录 --------------- /api:协议文件 /web: 静态web组件 -----------------通用应用目录 --------------- /configs:项目的默认配置 /init:system init (systemd,upstart,sysv) 配置 /scripts:执行各种构建、安装、分析等操作的脚本 /build:打包和持续集成 /deployments:部署配置 /test:测试 -----------------其他目录 --------------- /docs:文档 /tools:项目支持的工具 /examples:应用程序和公共库实例 /third_party:外部工具 /githooks: - /assets: 图片和其他存储的文件 /website:- 不应该有的目录 /src:请不要将项目级别的src目录和工作空间的src目录混淆。
|