关于go语言的那点事

关于,go,语言 · 浏览次数 : 307

小编点评

```go package writer import ( "os" ) var ( OsType = "Linux" // 公有变量 osType = "linux" // 私有变量 ) type FileWriter struct { Filename string // 共有成员变量 f * os.file // 私有成员变量 } // 公有函数 func NewFileWriter(filename string) (*FileWriter, error) { return &FileWriter{Filename: filename}, nil } // 私有函数 func newFileWriter(filename string) (fw *FileWriter, err error) { fw = &FileWriter{Filename: filename} fw.f, err = os.Create(fw.Filename) if err != nil { return nil, err } return fw, nil } // 公有方法 func (w *FileWriter) Write(data []byte) (n int, err error) { return w.f.Write(data) } // 公有方法 func (w *FileWriter) Close() (err error) { return w.f.Close() } // 私有方法 func (w *FileWriter) createFile() (err error) { return w.f.Create() } ```

正文

本篇是语言讨论的“传统项目”。每个写go语言讨论的人,都会介绍它的发展历程,应用领域,优缺点和特点来介绍go语言的那点事,当然这点事只是我从我的视角来看的。当然如果你有自己对go语言的看法,那就更好了,欢迎讨论!

“经典”简介

go语言由google公司开源的用于提高程序员编程效率的编程语言。它是一门简单易学,静态编译,原生并发以及向后兼容性的高效快捷的轻量级语言。

发展历程

目前go语言每半年会迭代一个新版本,从2012年的go1.0开始,已经历经21个版本,目前已经到了go1.20,从2015年开始进入快速发展期,以用于大型项目的工程语言进入人们的视野。

go语言在go1.1-g1.4时还不具备工程化的条件,但在go1.5时开始具备工程化的条件,这是因为(1)在go1.5之前的版本golang采用的是c语言编译器,(2)gc的STW时间会很长,(3)第三方包没有合理的存放位置。

而在go1.5版本开始实现go语言自举,在这个版本里开始采用三色标记法,这使得golang的gc时间大幅下降,经过go1.6-go1.7的改进,使得golang的STW时间大幅缩短,另外在这个版本开始实验vender机制。

这三个特性的加入使得golang在2015年之后开始火爆的原因,在go1.7正式使用vender机制,在go1.9版本STW时间缩短至100us以内,为此golang在go1.9版本已经完全具备工程化的条件。

之后golang在go1.11版本开始实验go mod机制以替换vender机制,在go1.13正式引入go mod机制,彻底解决了第三方库的版本问题,在go1.18版本中实验golang的泛型特性,而在go1.20版本中正式引入golang的泛型特性。


应用场景

go语言用于云原生开发,命令行接口,网站开发,运维开发领域以及存储开发。注意我这里介绍go语言的应用场景来自go语言官网实际上,你会发现go语言还能应用于其他领域,如数字货币(以太坊),物联网等等(因为我不熟悉这些领域,所以我可以假装不知道吗?)

云和网络服务

随着docker和kubernetes等杀手级应用的出现和发展,golang逐渐成为云和网络服务领域中举足轻重的语言,目前由超过75%的云原生计算基金项目都是使用go语言开发的。


命令行接口

对于命令行接口应用,go语言能够将其快速地构建成二进制程序,提供跨平台工作的开发方式以及强大的社区支持。我们可以在windows或者mac上开发或者调试,在Linux上编译部署。它通过静态编译构建的二进制程序即插即用,几乎不需要任何其他依赖。


例如,hub是github推出的用于辅助git的命令行工具,它是用go语言编写的。另外如greenplum的gpbackup和gprestore也是用go语言编写的。


网站

go语言不仅天生支持高并发,能以极小的开销约4K的内存启动一个携程goroutine,而且go语言的标准库对于web开发的强大支持,能让业务人员专注于业务开发,这些使得go语言在网站开发方面占有一席之地。

注意go语言其实已经有gin以及beego这样成熟的web框架,甚至有人已经将gin,vue3结合起来gin-vue-admin这样的项目。我的建议是如果你写的web服务很简单,那么go语言标准库基本已经够用,否则请选择上述框架。


运维

go语言在运维开发编写脚本时拥有大量优秀的标准库支持。另外,go语言还提供了丰富的工具链帮助用于编写高效、健壮以及可维护性强的程序。


目前在运维开发领域,使用go语言开发优秀的项目有类似于zabbix的Prometheus,将运维数据可视化的grafana,用于容器CI/CD的Docker CI/CD等等


存储

go语言是带有gc,高性能并且高并发的特点,为此在存储领域也有比较好的发展。例如分布式数据库tidb(sql层使用go语言开发)、时序性数据库influxdb、分布式kv存储etcd以及分布式消息队列nsq都是其中的佼佼者。


优点

简单易学

sum := 0
for i := 0; i < 30; i ++ {
    if i % 2 == 0 {
        sum += i
    }
}
fmt.Println(sum)

go语言许多语法和C语言很相似,学习难度和python类似,学习成本较低,大约1-2周初学者就能开发一些实用的小程序。当然如果你学过C语言,你将更快入门go语言


即插即用

go语言采用静态编译的方式,产生出的二进制程序即插即用,几乎无需其他依赖。

原生并发

c := make(chan int)
go func() {
    for {
        select {
        case e, ok := <-c:
            if !ok {
                return
            }
            fmt.Println(e)   
        }
    } 
}()

a := []int{5,2,4,3,1}
for _, v := range a {
    c <- v
}
close(c)

go语言可以很容易地实现并发编程,通过保留字go即可实现,使用chan实现携程间通信,你可以认为chan是一个加锁的队列或者消息管道。

如上,代码通过保留字go调用匿名函数启动了一个携程,并且通过chan向这个携程传值。

注意:chan的传入并非是全局变量而是因为go语言匿名函数的闭包特性。


社区支持

go语言虽然历经时间不多,但是它的社区支持极为强大,如上go语言目前支持常用数据库的访问。

向后兼容性承诺

使用go语言编写的代码会被其之后版本的go语言兼容,例如你用go语言1.8写了代码,那么几乎不用做出任何更改在go语言1.17中直接编译使用。这就意味着通过这个承诺,你几乎无需修改代码就能让go语言代码享受新版本带来的性能提升。

强大的标准库以及丰富的工具链

优秀的编译运行速度

go语言不仅有着c/c++,java等传统编译语言无法企及的编译速度,又有类似于c/c++的运行速度,这些让程序员有更好的编程体验。当然据说这是Google公司的阴谋,让程序员有“更多时间工作”。


缺点

  • go语言对GUI用户界面支持不够完善,需要额外的qt库支持或者采用wasm技术。
  • go语言对机器学习方面支持不够完善,存在神经网络和go语言对应库对接成本。
  • go语言不支持aix7.2以下的aix操作系统,这是由于go语言底层有少量通过汇编写成,对硬件有部分要求。
  • go语言对移动端app开发支持不够完善,在api使用上存在限制。
  • gol语言缺乏对传统异常捕获机制的支持,需要通过大量的if语句去判定其是否有有异常。

特点

这是相较于c/c++ ,java,javascript以及python等主流语言不一样的地方,不算是优点也不算是缺点的语言特性


多返回值

由于基本上目前的主流语言的函数都是单返回值,而golang为了使错误能够被返回,采用了含有多返回值的函数,如下:

func Write(data []byte) (n int, err error)

还有表达式中也可以使用多返回值,例如交换a,b可以写成

a:= 1
b:= 2
a,b = b,a

还有前面提到的

for _, v := range a {
    c <- v
}

以及

select {
    case e, ok := <-c:
    if !ok {
        return
    }
    fmt.Println(e)   
}

公有私有

golang并非通过指定关键字private和public去实现面向对象的封装特性,而是通过大小写去指定成员是否公有和私有,在下述代码中,writer包外的只能访问公有的成员变量,函数,或者方法。

package writer
import (
    "os"
)

var (
    OsType = "Linux"  //公有变量
    osType = "linux"  //私有变量
)

type FileWriter struct {
	Filename string //共有成员变量
    f * os.file     //私有成员变量
}

//公有函数
func NewFileWriter(filename string) (*FileWriter,  error){ 
    return newFileWriter(filename)
}
//私有函数
func newFileWriter(filename string) (fw *FileWriter, err error){
    fw = &FileWriter{
        Filename:filename,
    }
   	err = fw.createFile()
    return
}

//公有方法
func (w *FileWriter) Write(data []byte) (n int, err error){
   	return w.f.Write(data)
}

//公有方法
func (w *FileWriter) Close() (err error){
    return w.f.Close()
}

//私有方法
func (w *FileWriter) createFile() (err error){
    w.f, err = os.Create(w.Filename)
    if err != nil{
        return err
    }
    return
}

面向接口

golang由于采用了静态编译的方式,使得golang无法在运行时加载,为此它使用组合而没有继承,使用面向接口来实现面向对象的多态特性,这样更容易写出高内聚低耦合的代码。

例如我们定义一个接口

type Writer interface {
    Write(data []byte) (n int, err error)
}

然后上述代码中的FileWriter已经实现该接口

type FileWriter struct {
	filename string
    f * os.file
}

func (w *FileWriter) Write(data []byte) (n int, err error){
   	return w.f.Write(data)
}

网络同步编程

网络编程往往如下图采用异步回调的方式去完成事件处理。

但是在golang中网络编程可以使用同步模式去完成,这可能不是一个很好的例子。


func HandleConn(conn net.Conn) {
    defer conn.Close()
    for {
        buf := make([]byte, 1024)
		cnt, err := conn.Read(buf)
		if err != nil {
		    //请处理错误
	    }
        //处理信息
    }
}

func main() {
    listen, err := net.Listen("tcp", ":8888")
    if err != nil {
        //处理错误
        return
    }

    for {
        conn, err := listen.Accept()
        if err != nil {
            //处理错误
            return
        }

        go HandleConn(conn)
    }
}

与关于go语言的那点事相似的内容:

关于go语言的那点事

本篇是语言讨论的“传统项目”。每个写go语言讨论的人,都会介绍它的发展历程,应用领域,优缺点和特点来介绍go语言的那点事,当然这点事只是我从我的视角来看的。

crypto 加解密库简介与测试【GO 常用的库】

加密算法是任何语言都不可或缺的,关于 GO 语言的实现本文简单梳理了下,仅供参考。

Go泛型简介

Go语言的泛型是在Go 1.18版本中引入的一个新特性,它允许开发者编写可以处理不同数据类型的代码,而无需为每种数据类型都编写重复的代码。以下是关于Go语言泛型的一些关键点: 1. 泛型是通过在函数或类型定义中使用类型参数来实现的。类型参数可以被看作是一个特殊的类型,它可以在函数或类型定义中的任何位

关于开设go语言专题的说明

本专题写作的目的其实是分享go语言编程的使用场景,介绍go语言编程的方方面面,让大家能够用好这个由google公司发明的强力工具,提升大家在这方面的生产力,毕竟**”君子善假与物也“**嘛。 这里我先说明一下,我并不是一个对go语言的所有一切都认同的人,你会发现很多相关从业者也会吐槽go语言的“专制

GO 指针数据类型的使用

转载请注明出处: 在Go语言中,指针类型允许直接访问和修改某个变量的内存地址。通过使用指针,我们可以在函数之间共享数据或者在函数内部修改外部变量的值。 以下是关于Go语言指针类型的一些重要语法和示例: 定义指针变量: 使用*表示指针类型,并将其放置在变量类型前面。例如:var ptr *int声明了

Go结构体深度探索:从基础到应用

在Go语言中,结构体是核心的数据组织工具,提供了灵活的手段来处理复杂数据。本文深入探讨了结构体的定义、类型、字面量表示和使用方法,旨在为读者呈现Go结构体的全面视角。通过结构体,开发者可以实现更加模块化、高效的代码设计。这篇文章旨在为您提供关于结构体的深入理解,助您更好地利用Go语言的强大功能。 关

Gin中间件开发

Gin是一个用Go语言编写的Web框架,它提供了一种简单的方式来创建HTTP路由和处理HTTP请求。中间件是Gin框架中的一个重要概念,它可以用来处理HTTP请求和响应,或者在处理请求之前和之后执行一些操作。 以下是关于Gin中间件开发的一些基本信息: - **中间件的定义**:在Gin中,中间件是

Go语言性能剖析利器--pprof实战

作者:耿宗杰 前言 关于pprof的文章在网上已是汗牛充栋,却是千篇一律的命令介绍,鲜有真正实操的,本文将参考Go社区资料,结合自己的经验,实战Go程序的性能分析与优化过程。 优化思路 首先说一下性能优化的一般思路。系统性能的分析优化,一定是从大到小的步骤来进行的,即从业务架构的优化,到系统架构的优

Go 语言内置类型全解析:从布尔到字符串的全维度探究

> 关注微信公众号【TechLeadCloud】,分享互联网架构、云服务技术的全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。 > 本文深入探讨了 Go 语言的内

在Go中如何实现并发

Go语言的并发机制是其强大和流行的一个关键特性之一。Go使用协程(goroutines)和通道(channels)来实现并发编程,这使得编写高效且可维护的并发代码变得相对容易。下面是Go的并发机制的详细介绍: 协程(Goroutines): 协程是Go中的轻量级线程,由Go运行时管理。与传统线程相比