(go语言)(go语言官网)

(go语言)(go语言官网)

1 go的整体思想

go不同于C++ java 语言,使用对象、属性、继承、多态来组织整个程序结构。

go的风格整体倾向于js,python,js两大特点,一是原型链 二是聚合 优于 继承,面向对象带来好处的同时,带来了臃肿和藕合问题,go尝试用包的方式变轻快。

实际上现代语言没有革命性的创新,都是对同样问题的不同解决方式,好的语言特性大家会使用,其他语言实现不好的地方,想办法改进。

2 go 语言没有类

但是go语言使用包(package)来维护代码访问,这个风格与面向对象不同。

java:

import com.****.test.UserInfo;

UserInfo userInfo = new UserInfo;

userInfo.setName("****");

String strName = userInfo.getName();

go:

import (

"com.****.test"

)

test.setName("****");

vale := test.getName

这里使用package.func 就是使用包来组织函数。

问题:

1个package下边可能有多个文件,这个函数不知道在哪个文件中,可以点击代码跟踪过去,但是不够直观。

3 go语言的import

import (

"fmt"

testgin "github.com/gin-gonic/gin"

_ "testgo1/app/api"

)

1 指定包的别名

testgin

2 前面有一个下划线 _

这个表示,只引入包,并且在初始化是调用包内的 init函数,但是并不需要访问别的代码。

4 init函数

go 保证各代码文件中的init函数只被调用1次

go 会分析文件之间的import关系,从而决定先调用那个init,后调佣那个init

init 函数的调用,限于其他函数,可以在init中做变量的初始化工作

5 go.mod

这是工程的配置文件,在这个文件中维护如下信息

module testgo1

go 1.16

require (

github.com/Shopify/sarama v1.30.0 // indirect

github.com/gin-contrib/zap v0.0.1

github.com/gin-gonic/gin v1.6.3

github.com/mitchellh/go-homedir v1.1.0

github.com/seanlan/packages v0.1.0

github.com/spf13/cobra v1.2.1

github.com/spf13/viper v1.8.1

go.uber.org/config v1.4.0

go.uber.org/zap v1.17.0

)

工程的名字,或者说自己的工程的包路径,用于程序内部引入其他包时的路径前缀

使用的go语言的版本引入的三方库的地址 和 版本,统一在这里配置

这类似于java的pom.xml, python的 main.spec, swift的 Podfile

6 vendor机制

vendor机制,用于维护go工程的三方库,具体的做法是:

0 在工程根路径下建vendor文件夹

1 在go.mod中配置三方库url和版本

2 执行go mod vendor

然后,就会下载三方库,并放到vendor目录下,thinkphp也有vendor路径,用途相似

3 go会优先使用vendor下的库,而不是仓库中的三方库

4 vendor的目的是保留三方库的版本代码,作为特定版本的副本使用

go mod vendor 的机制,和iOS开发pod 很像 Podfile 和

pod install 会生成新的工程,而且会下载三方库到本目录的 pods 文件夹下

这种机制,简单而高效

我们也看下python3的类似机制

// 这句能在工程路径下生成 venv文件夹,并且包含纯净的当前版本 python环境

python3 -m venv myProject

// 下面这句,把环境切换到虚拟环境

source ./myProject/bin/activate加载虚拟环境环境变量

// 安装linux依赖,并且把依赖包安装到了虚拟环境

// myProject/lib/python3.8/site-packages/文件夹下

pop install redis==3.5.1

// 退出虚拟环境

deactivate

7 func 函数

func GetValue(code *int, info string) (left *int, fight int) {

if code == 1 {

return 1, 1 // 直接返回值,不使用返回变量名

}

if code == 2 {

left = 2

right = 2

return // 使用返回变量名字

}

if code == 3 {

left1 = 3

right = 3

return left1, right1 // 使用替换掉的返回变量名

}

1 可以有多个返回值,类似swift中的元组的概念

2 返回值和传参,都可以使用指针

3 func 关键字,在C++ 和 java中都是不使用的

8 变量的名字 方法名字 大小写

go 约定:

首字母大写的变量 和 函数,相当于其他语言的 public

首字母小写的变量 和 函数,相当于其他语言的 private

9 结构体

1 基本概念

就像C语言一样,虽然不继承和多态,封装的思想是必要的。

type JsonResponse struct {

Code int

Message string

Data interface

}

2 方法接收器

func (jsonRes *JsonResponse) getMesage() string {

return jsonRes.Message

}

func (jsonRes *JsonResponse) setMesage(msg string) {

jsonRes.Message = msg

}

我们可以看出,都是对结构体成员的操作的方法。

jsonRes 称为接收器,这样的方法类似面向对象的类和方法,同样思想的变种。

3 方法的本质

类似于C++与C的关系,把this作为函数的第一个参数。

编译器会把 接收器 作为函数的第一个参数,这样方法就是把接收器作为第一个参数的 普通函数

js 和 python都是这样干的,其他语言引入面向对象思想的时候,就把this封装成第一个参数,类似python干脆要自己写,都不隐藏。

10 defer 语句 与 java finally

java 一般 try{} finally 或则 try catch finally,都是连在一起用的。

go defer 不与try 一起使用。

defer 用在函数内部,保证无论panic 还是 return,出函数之前,都会执行 defer 后面的语句

如果有多个defer函数,按照压栈的顺序,后进先出。

func a(){fmt.Println("funca")}

func c(){

defer func a()

defer func b(){fmt.Println("funcb")}()

fmt.Println("func c")

}

11 接口与实现接口

1 接口可以定义一组方法,不定义实现

举例子:

type TestInterface1 interface {

func method1(i int) int

func method2(str string)

}

2 interface{} 类似java的根类,Object,如果函数接受一个interface{}类型的参数,可以当未知类型使用,传什么参数都可以。

3 go对接口 和 实现类之间,采用松散的约定方式

go 采用组合的方式,解决继承的问题。所以,go并没有 extends public impliment 等这样的关键字 放在类名字的后面,也没有class

go一个类型的方法集合 是 接口方法集合 的超集。我们就说它实现了这个接口。编译器在检查的时候,就不会报错。

从程度来讲,这并不像面向对象 extends 那么直观。没办法,使用组合就会这样,你也会享受松散的好处。

12 tag

tag类似于java 的注解,java的注解分为注解的声明 和 注解的 解释器,这个过程会用到反射。

go 的tag类似,用到struct字段后边,去获得额外的信息。

1 tag是结构体的一部分

tag 和结构体的字段一起使用,并基于反射发挥作用

2 tag基本规则

tag是字符串,放在结构体字段后边。

tag以反引号 ``包围,key:value 形式,value要用""包围,冒号两边不能有空格。

举例:

type PayServer struct {

ServerName string `key1:"value1 key2:"value2"`

ServerIP string `key1:"values1"`

}

func main(){

s := PayServer{}

st := reflect.TypeOf(s)

field1 := st.Field(0)

fmt.Printf("key1:%v\n", field1.Tag.Get("key1"))

}

可以看出,这里relect使用的场景,解析的方式。

场景是受限的,解析方式是简单的。可能觉得java反射太复杂了,go也不是解释执行的,只把最常用的部分实现就可以了。

13 go import

go import 有点类似 python 的import

python的class写法,明显是一种封装,非常形式主义

go为了支持类似的功能,搞出来了接收器,也是一种解决方案

python 的 from *** import ***

import (

"fmt"

"github.com/seanlan/packages/gjson"

"io/ioutil"

"net/http"

)

go用的是/,不是.

14 go const

const (

BASE_URI = "http://card.com:8081"

)

15 map 及 遍历

var params = map[string]string{

"123":"456",

"789":"33444",

}

for k, v := range params {

uri = uri + k + "=" + v + "&"

}

go里边的map,结合 interface{},有点类似php中的map,啥都能放,一个map使用范围极广。

16 go 变量

var a int32

b := 5

两种形式,一种声明形式的,一种简写,声明并赋值

17 函数的多个返回值

java 函数只有一个返回值,使用起来极不方便,因为很多时候,你希望有两个返回值,比如网络请求,成功了使用response返回,错误了试用error回复失败的原因。

为此,springframework还发明了 Pair,但这都不是语言层面的支持。

go 在语言层面支持了任意数量的返回值,就非常方便,比如:

func GetShopList(lng float64, lat float64, categoryId int32, startIndex int32, sortType int32) (gjson.JsonObject, error) {

这就明确告诉你,要么处理json,要么通过error取错误原因

上面关于go的总结,并不是像其他的书那样,罗列的入门的知识。二是已经熟悉java C++ python等语言的基础上,通过对比的方式学习go语言。

声明:我要去上班所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,版权归原作者用户9724805569861所有,原文出处。若您的权利被侵害,请联系删除。

本文标题:(go语言)(go语言官网)
本文链接:https://www.51qsb.cn/article/m8c0r.html

(0)
打赏微信扫一扫微信扫一扫QQ扫一扫QQ扫一扫
上一篇2022-12-28
下一篇2022-12-28

你可能还想知道

发表回复

登录后才能评论