阅读前,读者需要掌握java的语法基础,最好有python和c++的基础。
方便理解。
参考:
Golang官方:
https://golang.google.cn/tour/welcome/1
bilibili:
【尚硅谷】Golang入门到实战教程丨一套精通GO语言
go基础
①go的执行流程
两种方式
- go build
- build:将go文件编译为二进制.exe的可执行文件。
- 编译好之后直接运行exe文件
- go run
- build和运行合并。
②go语法要求和注意
从Java转go,需要注意:
- 后缀扩展为go
- 入口:main
- 严格区分大小写
- 行尾不用加分号
- go编译器是逐行编译,一行只能写一句
- import 包必须使用
③其他语法:
1. 转义字符
这里类似于c语言,与c如出一辙。
2. 常见错误和解决办法
找不到文件?
可能是名字写错了。。
语法错误
大多是依法不习惯
package mian(我遇到的,不是main居然不能启动)
3. 注释comment
- 行注释
- 块注释
4. go代码规范和风格
官方推荐:
尽量使用行注释
正确的缩进和空白。
- 快捷键的方式
- gofmt进行格式化
- gofmt -w xxgo 重写(格式化)
{
:其中代码块的这个左阔符必须在方法同一行,不允许换行。
代码一行不要超过80字符。类比python
采用换行。
5. 常用api语言标准库
中文文档
英文文档
https://pkg.go.dev/search?q=fmt
go中函数的使用:
使用包名package加函数名字进行调用。
6. dos常用命令
win平台的熟悉,win的操作终端。terminal
7. 变量
变量三要素:
变量名+ 值 + 数据类型
- 定义
- 赋值
- 使用
golang中变量的使用有三种方式:
- 指定类型,声明后不赋值,使用默认值。
- var demo int
- 不写类型,直接赋值用var,自行判定变量类型
- 不使用var, 使用:=
使用:
var n1, n2, n3 int
var n, m = 1, 2
8. 数据类型
- 基本数据类型
- 数值
- 整数(有符号,无符号):int(其中没有short/long,直接int32或者int64可以为指定长度),uint
- 特别的:rune(是为:int32的别名)
- 但是:特别注意:Unicode
- 用于处理带有中文的字符串。
- 浮点数(float32【可能造成精度损失较于64没有那么准】,float64)
- 单精度32和双精度64
- 优先float64
- 字符:通常用byte表示,使用byte来保存单个的字母字符。
- byte:与uint8等价。
- 字符用byte
- go中用的utf-8表示字符
- byte:与uint8等价。
- 布尔:bool
- 一个字节
- 字符串:string,
- 引号:“ str ”
- 反引号:``rev str
\
- 数值
- 复杂/派生数据类型
- 指针:Pointer
- 数组:【】
- 结构体:type struct
- 管道:chan:channel
- 函数:func
- 切片:slice(通过make)
- 动态数组
- 接口:interface
- map:字典类似python。类似java集合
使用细节:
- Go中需要显式的强制转换,区别于Java/c
- 其中转换类型的是其值,变量本身并没有类型变化。
- %T 可以看其数据类型
- %v
- %q : 加引号
- 占用字节大小?
unsafe.sizeof(Type)
: 字节大小
基本数据类型转string
func Sprintf( format string, a …interface{} ) string
interface{} 表示任何数据类型
strconv. FormatInt( num int, base int )
func strconv. Itoa(num int)string
其中base 是转换进制
string转基本数据类型
strconv包
func parse**
复杂类型
- 指针
内存布局?
- 基本数据类型
- 值类型
- var num int:&num获取地址
- 通常在栈内存中分配
- 引用类型
- 指针,map,slice, channel, interface
- 在堆中,若没有引用了,最后由GC处理
- 值类型
9. Go标识符命名特点和规范
- 包名
- package
- 保持其名字和目录名字一致
- package
- 驼峰法命名
- 首字母大写:类似于public。其他包可以访问。
- 小写:私有:private。
10. 运算符
如果您有Java基础,这些个就差不太多。
特别的,go里面没有三元运算。
细节,易错:
++,–,只能独立使用且只能写在变量之后,区别于Java/c;更简洁。
&&:短路与
||:短路或
交换两个数:
在Go里面有四种方式:
- 临时变量法
- 位运算异或
- 加减操作:
- a = a+b; b = a-b; a= a-b;
- 多赋值:
- a, b = b, a
位运算
注意GoLang中没有>>> 无符号右移,区别于Java。
其他情况类似相同。
11. 获取用户终端输入
- fmt. scanfln()
- 获取一行的内容。
- fmt. scanf()
--------------------------------更 -----------------------新----------------------------------
④流程控制
1. 顺序控制
就是一般代码的顺序执行
2. 分支控制
特别的,表达式括号不是强制不写,可以写,但是没必要。
-
单分支
- 一般的 if, 条件表达式
- 区别于Java,无需括号,且大括号必须要有
-
双分支
- 与Java类似,只是需要强调,没有括号,并且else必须在if 反括号的后面。
-
多分支
除了有,if-else if -else
还有:
switch:
这里区别于Java,
区别与相同:
-
switch后可以不加表达式:此时功能类似于if-else分支
-
switch后面也可以直接声明定义一个变量,分号结束,但是不推荐使用。
- 例如:switch age := 111;(注意这个分号必须要写){ case age ==111:, , … default. }
-
不用break,
- 但是可以加:fallthrough:进行case穿透,到下一个case。
-
case里面可以放多个表达式,用逗号隔开
- 注意:常量不能重复,但是变量无法识别值是否相同,可以变量值重复
同:
- 都不执行case后可以有default。
3. 循环控制
for i:=0;i<n;i++{
//...
}
for ;true;{// for true{ ... }
//...
}
基础部分待更新
…
----------------------------更-----------------------------------------------------新2----------------------------------
GoWeb
Go Web 框架:
注意:go本身有net/http库对web开发,基于此出现了很多框架:
- Gin:微框架
- Kratos(b站开源)
- Beego:快速开发Go应用的框架, 灵感:tornado,sinatra,flask。
- Iris
- Ginex(字节开源)
需要了解:go get:类似于git clone
①Gin
开门第一课:先看看入门hello world:
package main
import (
_ "fmt"
"github.com/gin-gonic/gin"
)
func main() {
// create one server
r := gin.Default()
// some other operation:
// link to mysql etc.
// get
r.GET("/halo", func(c *gin.Context) {
c.JSON(200, gin.H{
"msg": "this the gin simple framework",
})
})
// spring boot run; server port
err := r.Run()
if err != nil {
return
}
}
前后端分离基础
用什么?
和Java 一样,和前端,用RestFul API。
get: /restful
post: /restful
put: /restful
delete: /restful
1.类似Java后端的template: 给前端响应页面,纯go的web项目
// 后端写静态页面并传值给静态的html:
// 加载静态页面:
r.LoadHTMLFiles("templates/*")
r.Static(relative, root)
// get
r.GET("/halo", func(c *gin.Context) {
c.JSON(200, gin.H{
"msg": "cheng jiang with cheng haiyan",
})
c.HTML(http.StatusOK, "index.html", gin.H{
"msg": "this the back send data",
})
})
2.获取请求中的参数
非rest ful
// halo/info?name=chengjiang&age=20
r.GET("/halo/info", func(c *gin.Context) {
name,age := c.Query("name"), c.Query("age")
fmt.Println(name, age)
})
restful:
// restful:
// halo/info/chengjiang/20
r.GET("/halo/info/:name/:age", func(c *gin.Context) {
name, age := c.Param("name"), c.Param("age")
fmt.Println(name, age)
})
3.获取前端的json并序列化解析,类似Java
r.POST("/halo", func(c *gin.Context) {
data, _ := c.GetRawData()
var m *map[string]interface{}
_ = json.Unmarshal(data, m)
c.JSON(http.StatusOK, m)
})
表单:
r.POST("/halo", func(c *gin.Context) {
name := c.PostForm("name")
//...
})
路由:
c. Redirct(code, url)
接下来重点来了昂:
4.路由组:
// group
group := r.Group("/user")
{
group.GET("/info")
// ... post, put, delete
}// url: user/add
5.中间件:(Java中拦截器)
预处理,登录,授权,验证,分页,耗时统计, 支付
func myHandler() gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("sesion", "session-id")
c.Next() // run
c.Abort() // refuse
}
}
//main:
r.GET("/halo/info", myHandler, func(c *gin.context){
// ...
})
6.数据库:Xorm/ Gorm
基于Go的ORM 库,实现数据库操作。
安装:
go get xorm.io/xorm
- struct 和 数据库表 映射。自动同步。
- engine. Sync( new( user_table_struct ) )
- 事务支持
- SQL 和 ORM操作并行
- 缓存
- 级联接加载struct
② Kratos学习
- 个人项目练习:https://gitee.com/cdu-phm/back
- 由于学习内容较多,详细学习记录,等待另开一个blog进行更新。
参考b站提供开源官方文档:
https://go-kratos.dev/
https://go-kratos.dev/docs/
③.Go to NoSQL: Redis
使用的是:github.com/go-redis/redis/v8
----------------------------更-----------------------------------------------------新----------------------------------
Go的实习之路
更新于2023.02.07
谈谈从Java到GoLang的实习之路叭:
技术路线的成长
技术积累:
从开始实习到目前:
- java - go。的过渡
- 框架:kratos,gin,beego。protobuf。
再到微服务的整体理解。还未去了解:ServiceMesh - 数据库:MySQL:使用gorm,module(对go-jet的封装)
- 通讯协议:websocket,mqtt(learning),socketio,这个主要用于IM系统的实现
- 文件存储:阿里云OSS,MinIO。
- Docker的使用,docker-compose。
- 工具:cobra命令行。
- 流水线CI/CD:jenkins, drone;
- nginx配置,upstream等。
学习案例
使用Go结合框架Kratos和socketio简易版线上聊天:
golang 测试代码:
// @author <chengjiang>
// @date 2023/1/11
// @note
package test
import (
"fmt"
socketio "github.com/googollee/go-socket.io"
"log"
"net/http"
"strings"
"testing"
)
func TestSocketio(t *testing.T) {
server := socketio.NewServer(nil)
server.OnConnect("/", func(s socketio.Conn) error {
s.SetContext("")
fmt.Println("connected: ", s.ID())
// Join: self-defining, the room:
s.Join("my_room")
return nil
})
// 事件
server.OnEvent("/", "notice", func(s socketio.Conn, msg string) {
fmt.Println("notice:", msg)
var msgs = strings.Split(msg, "|")
var name = msgs[0]
var mesg = msgs[1]
server.BroadcastToRoom("/", "my_room", "reply", "the user: "+name+", this is to web: "+mesg)
})
server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string {
s.SetContext(msg)
return "recv " + msg
})
server.OnEvent("/", "bye", func(s socketio.Conn) string {
last := s.Context().(string)
s.Emit("bye", last)
s.Close()
return last
})
// error
server.OnError("/", func(s socketio.Conn, e error) {
fmt.Println("meet error: ", e)
})
server.OnDisconnect("/", func(s socketio.Conn, reason string) {
fmt.Println("closed", reason)
s.LeaveAll()
})
//
go server.Serve()
defer server.Close()
http.Handle("/socket.io/", server)
http.Handle("/", http.FileServer(http.Dir("./asset")))
log.Println("Serving at localhost:8000...")
log.Fatal(http.ListenAndServe(":8000", nil))
}