学Golang,看这一篇

news2025/8/12 0:12:05
去年学了一遍 Golang,发现都给整忘了, 好饭不怕晚,再次二刷。 其实学好 Golang 并不难,关键是要找到它和其它语言不同和众里寻他千百度相通的微妙之处,就能很优雅地使用 Golang,以下会涉及较多知识点。

特殊类型

1: 空结构体 类型 struct{}, 空结构体的实例 struct{}{}

2: 空接口 类型 interface{}

会自动执行的函数

fun init(){}  // 会自动执行
  • init 函数先于 main 函数自动执行,不能被其他函数调用;
  • init 函数没有输入参数、返回值;
  • 每个包可以有多个 init 函数;
  • 包的每个源文件也可以有多个 init 函数,这点比较特殊;
  • 同一个包的 init 执行顺序,golang 没有明确定义,编程时要注意程序不要依赖这个执行顺序。
  • 不同包的 init 函数按照包导入的依赖关系决定执行顺序。

匿名函数

1: 需要传递匿名函数的地方:

 once.Do(func() { // 该函数只会执行一次
  fmt.Println("Create Obj")
  singleInstance = new(Singleton)
 })

2: 如果一个函数需要返回一个匿名函数:

type retFunc func()  // 通过 type 创建一个  别名

func xxx() retFunc{
 return func(){
  return 1;
 }
}

更凶残的匿名函数:

 writeDataFn := func() {
  var data []int // 往 slice 里 写100 个数;
  for i := 0; i < 100; i++ {
   data = append(data, i)
  }
  atomic.StorePointer(&shareBufPtr, unsafe.Pointer(&data)) // 写完后,将共享缓存的指针指向它;
 }

 readDataFn := func() {
  data := atomic.LoadPointer(&shareBufPtr)
  fmt.Println(data, *(*[]int)(data)) // 打印共享缓存里的值
 }

接口

1: 注意接口是 type xxx interface{} 2: 传入接口的地方不能是指针 p *Programmer:

func writeFirstProgram2(p *Programmer) {
 fmt.Printf("%T %v\n", p, p.WriteHelloWorld())
}

如果接口要传入这个,则必须定义返回值为 interface{} 的方法:

type Programmer interface {
    WriteHelloWorld() interface{}
}
注意: 1:父接口,只能是实例,不能是指针,可以看成父接口本身代表的就是指针实例 2:子类以 指针/实例 实现的接口,传入时,就得以对应的指针实例传入接口 3: 一个接口,通常 只定义 一个 方法,尽量保证  接口精简

行为

1:行为的定义时 type xxx struct{}

2:行为的方法实现,决定了最终传入的实例是什么

type Programmer interface {
    WriteHelloWorld() string
}

第一种: 子类实现 func (p *NoTypeProgrammer) WriteHelloWorld(), 则 只能被 指针调用

// 将 子行为 传入接口
type NoTypeProgrammer struct {
}

// 标识,要看最终这里的实现 !!!
func (p *NoTypeProgrammer) WriteHelloWorld() string {
    return "System.out.Println(\"Hello World!\")"
}

// 传入接口的  方法, 这里传 指针or实例都可以的
func writeFirstProgram(p Programmer) {
    fmt.Printf("%T %v\n", p, p.WriteHelloWorld())
}
方法前面传入对象,是为了通过对象.s 调用内部的成员变量or成员函数

调用:

    noTypeProg := new(NoTypeProgrammer)
    writeFirstProgram(noTypeProg)
    //writeFirstProgram(NoTypeProgrammer{}) // error

第二种:子类实现 func (p oTypeProgrammer) WriteHelloWorld() , 则指针和实例都可以:

// 标识,要看最终这里的实现 !!!
func (p NoTypeProgrammer) WriteHelloWorld() string {
    return "System.out.Println(\"Hello World!\")"
}

调用:

    noTypeProg := new(NoTypeProgrammer)
    writeFirstProgram(noTypeProg)
    writeFirstProgram(NoTypeProgrammer{}) // right

空接口

1: 空接口,代表 object 类型。需要通过断言判断类型

func DoSomething(p interface{}) {
 switch v := p.(type) {
 case int:
  fmt.Println("Integer", v)
 case string:
  fmt.Println("String", v)
 default:
  fmt.Println("Unknow Type")
 }
}

// 使用
DoSomething("10")

2:空接口可以接受任何类型的值:

var yzj interface{} // 空接口的使用,空接口类型的变量可以保存任何类型的值,空格口类型的变量非常类似于弱类型语言中的变量,未被初始化的 interface 默认初始值为 nil。

错误处理

1:使用多返回值,错误码来判断程序的处理;类似于 C ,通过引用或者指针传出来错误码;【最佳的是返回码 + 引用】;

模块

  • 同一个目录下只能有一个包名;
  • 包名推荐与目录名保持一致;
  • 每一个包内,只能有一个同名函数;
  • 同一个 package 内的 函数, 变量可以随意调用,不用导入

CSP

1:Communication sequential process: 进程间通过管道进行通信。

2:channel 的两种通信方式:

  • buffer- channel: 发送者和接受者有更松的耦合关系;
  • 容量没满, 放消息的人可以一直往里面放; 若容量已满, 直到接受者收走一个消息,能继续放入消息了,才能继续往下执行;
  • 接收者也类似: 只要是非空,能一直拿消息,向下执行;如果没有消息,需要一直等待,然后再向下继续执行;

单通道: chan string, chan int, 一次只能放入一个值, 在 值 被取走前, 通道是阻塞的。

3: 创建一个协程,除了 go func(){} 还有更简洁的方式:

go agt.EventProcessGroutine()   // 直接go 后面接一个 实名函数 也可以

协程是异步的, 主线程只会因为 通道阻塞

sequenceDiagram
    main ->> main:

    main ->> + AsyncService : 异步执行
    main ->> +otherTask: 和 AsyncService 同步执行
    otherTask-->>- main: return
    main ->> main: 等待 <-channel
    AsyncService ->> AsyncService: sleep
    AsyncService ->> AsyncService: sleep
    AsyncService ->>main: retCh <- ret, 通道在左边,是给通道赋值
    main ->> main: 唤起执行
    AsyncService ->>AsyncService: 继续执行
	main ->> main: End
	AsyncService ->>AsyncService: 继续执行
	AsyncService -->>- main: return

3:主线程可通过 var wg sync.WaitGroup() 管理多个协程的并发问题;

4: 生产者和消费者之间通过生产者的 close(chan) 来广播结束通道,

5: // 通道没关闭,其它协程会陷入死循环;

close(chan) 给其它协程广播的是 struct{}{} 空消息;

6: 可用于任意任务完成的场景。

一个 buffer 会阻塞其它协程的 写, N 个协程创建 N 个 Buffer, 就是非阻塞的了。

ch := make(chan string)

7: sync.WaitGroup() 等待所有协程返回:

8: 利用 channel 自身取的阻塞,有多少个协程,就循环多少次:

Select

资料领取直通车:Golang云原生最新资料+视频学习路线

Go语言学习地址:Golang DevOps项目实战

 

Context

1: 可通过父协程取消所有子协程(非 Channel 实现)。

Sync.Once.Do()

1: sync.Once 的 Do() 方法,可保证匿名函数只被执行一次

对象池

1: 对象池中如果需要放入任意的数据类型,就放入 interface{}

sync.Pool

1: 生命周期不可控,随时会被 GC

bench

1:

2: bench 只能做参考,在不同的方式下,运行的次数不同。

3: bench 的使用

func BenchSyncmap(b *testing.B) {
 // bench 需要传入一个函数
 b.Run("map with RWLock", func(b *testing.B) {
  hm := CreateRWLockMap()
  benchMap(b, hm)
 })
}

反射

1: 可反射成员方法,编写更灵活的代码;

2: 特别是在解析 json 的时候;

3: 名字可以不一样,但是类型一样即可。 【万能程序】

不安全的编程

1: 类型转换

2: 可通过 atomic.StorePointer() 和 actomic.LoadPointer() 对多个协程并发读写:

实际上读和写是分开的两个 Buffer:

pipe 和 Filter

1: 定义接口

2: 定义每个接口Filter的 工厂方法 + 数据处理方法 【工厂方法 在很多 库里都用到了,这种设计方式可成为定式 】

3: 串起来调用:

一个更常用的测试用例:

需要测试的接口,可以将各种实例放进去:

实现一个 接口的经典例子【golang 的类组织方式,采用的是更扁平化的方式】:

创建对应的接口,并最终调用它:

microKernel

1: 微服务模式, 总类管理子类的过程;

JSON

1:通过 struct tag 来解析,相对比较简单,有点类似那个万能程序;

2:easyjson 需要手动生成 marsh 和 unmarsh 文件;

HTTP 服务

1: ROA:面向资源的架构

性能分析

1: 常见性能调优过程:

2: 性能分析的常见指标:

  • 1:Wall Time;
  • 2: CPU Time;
  • 3: Block Time;
  • 4: Memory Allocation;
  • 5: GC Times/Time Spent

3: prof 常用指令:

  • 1: 查看CPU:
 go test -bench=.
 go test -bench=. -cpuprofile=cpu.prof
 go tool pprof cpu.prof top -cum list function
  • 2: 查看 Mem:
go test -bench=.
go test -bench=. -memprofile=mem.prof
go tool pprof mem.prof
top
list function

也可调用 对应的API,对某个函数 精准的输出 prof 文件

4: 网络查看: http://localhost:8081/debug/pprof/

5: 影响性能的几个要点:

文本处理和字符串连接

  • json 解析;
  • 字符串连接 用 bytes.Buffer 或 strings.Builder

协程锁:

  • 少用读锁;
  • 多用 concurrent-map, 实现协程安全的 数据共享;

GC 友好代码【尽量复用内存,减少内存分配】:

  • 大数组和结构体,在函数中传递时,使用指针;
  • 切片 最好初始化到合适的大小; 或者 用数组;

面向错误的设计

1: 隔离错误:

  • 从设计上隔离: Micro-kernal 设计;
  • 物理隔离,部署;

2: 重用和冗余的适当取舍;

3: 限流;

4: 快速拒绝比慢响应更优;(从web 的角度)

5: 不要无休止的等待;

6: 断路器: 利用好缓存,适当容错;

面向恢复的设计

1: 注意僵尸进程: 池化资源耗尽 和 死锁;

2: Let it crash 大多数 比 recover 程序更优(尽早发现错误尽早解决);

3: 构建可恢复的系统:

  • 拒绝单实例;
  • 减少服务之间依赖;
  • 快速启动;
  • 尽量 无状态;

4:与客户端协商访问频次, 类似限流;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/15292.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(Java高级教程)第一章Java多线程基础-第一节6:多线程案例

文章目录一&#xff1a;单例模式&#xff08;1&#xff09;设计模式概述&#xff08;2&#xff09;单例模式概述&#xff08;3&#xff09;单例模式实现A&#xff1a;饿汉模式B&#xff1a;懒汉模式①&#xff1a;单线程版②&#xff1a;多线程版③&#xff1a;多线程版&#x…

alpha模型:打开量化投资的黑箱;附创业板布林带策略代码:年化15%。

原创文章第108篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑&#xff0c; AI量化投资”。 关于量化投资&#xff0c;我们写了不少文章。从数据准备&#xff0c;预处理&#xff0c;因子特征工程&#xff0c;因子分析&#xff0c;规则策略&#xff0c;模型&#xff0c…

平安城市解决方案-最新全套文件

平安城市解决方案-最新全套文件一、建设背景目前平安城市视频监控面临的主要问题&#xff1a;1、看不清2、传不回3、存不下4、找不着5、易泄露二、思路架构三、建设方案四、获取 - 平安城市全套最新解决方案合集一、建设背景 平安城市是一个特大型、综合性非常强的管理系统&am…

JSP文件上传

JSP 提供了上传和下载的功能&#xff0c;用户釆用此功能&#xff0c;可以轻松实现文件的传输。下面介绍文件上传与下载的操作。 用户通过一个 JSP 页面上传文件给服务器时&#xff0c;该 JSP 页面必须含有 File 类型的表单&#xff0c; 并且表单必须将 enctype 的属性值设置为…

Node.js 是怎么找到模块的?

大家好&#xff0c;我是前端西瓜哥&#xff0c;今天我们来看看 Node.js 模块查找的原理。 模块种类 模块有三种来源。 核心模块&#xff1a;Node.js 内置的包。比如 http、fs、path&#xff1b; 自定义模块&#xff1a;NPM 包。比如 axios、express&#xff0c;位于 node_mo…

virtualBox虚拟机之间网络互通设置

环境 主机&#xff1a;Win10 虚拟机&#xff1a;Ubuntu 20.04 虚拟机&#xff1a;VirtualBox 6.1 模式虚拟机→主机主机→虚拟机虚拟机↔虚拟机虚拟机→Net/LANNet/LAN→虚拟机NAT√端口转发√端口转发NATservice√端口转发√√端口转发Host-Only√√√Internal√Bridged√√…

【快速上手系列】用于登录的验证码制作(ValidateCode)和Javaweb自带的老式验证码快速上手

【快速上手系列】用于登录的验证码制作&#xff08;ValidateCode&#xff09;和Javaweb自带的老式验证码快速上手 验证码 简介 验证码&#xff08;CAPTCHA&#xff09;是“Completely Automated Public Turing test to tell Computers and Humans Apart”&#xff08;全自动…

易基因|疾病研究:DNA甲基化和转录组学特征在高浆卵巢癌复发和耐药过程中高度保守

易基因&#xff5c;疾病研究&#xff1a;DNA甲基化和转录组学特征在高浆卵巢癌复发和耐药过程中高度保守 大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 2022年07月27日&#xff0c;《J Exp Clin Cancer Res》杂志发表了题为“DNA me…

Linux|centos7下部署安装alertmanager并实现邮箱和微信告警(三)

前言&#xff1a; 前文Linux|centos7下部署安装alertmanager并实现邮箱和微信告警&#xff08;二&#xff09;_晚风_END的博客-CSDN博客 实现了告警系统模块的部署和测试&#xff0c;主要的告警范围是服务器节点的操作系统内存&#xff0c;磁盘空间的使用率这些方面&#xff0…

甘露糖-聚乙二醇-N-羟基琥珀酰亚胺mannose-PEG-NHS

甘露糖-聚乙二醇-N-羟基琥珀酰亚胺mannose-PEG-NHS 琥珀酰亚胺又称为丁酰亚胺或丁二酰亚胺&#xff0c;是一种无色针状结晶或具有淡褐色光泽的薄片固体&#xff0c;味甜。易溶于水、醇或氢氧化钠溶液&#xff0c;不溶于醚、氯仿等&#xff0c;可以提供PEG接枝修饰甘露糖&#…

精彩回顾!2022VisionChina深圳展圆满落幕

11月16日&#xff0c;维科杯•OFweek 2022中国工业自动化及数字化行业年度评选颁奖典礼在深圳大中华喜来登酒店举行&#xff0c;经过OFweek网络投票、专家组评审及组委会综合评审三轮激烈紧张的评选&#xff0c;昂视凭借“PiqsVT智能视觉系统”在近300个参评项目中脱颖而出&…

Linux三个踩坑过程记录

今早花了一早上的时间解决了三个Linux的问题&#xff0c;分别是读写权限、克隆虚拟机开启问题和Xshell连接VM虚拟机问题。平时用虚拟机比较少&#xff0c;现在刚一开始用&#xff0c;就给我来了三个问题让我解决&#xff0c;真是含泪解决问题&#xff0c;但现在解决了&#xff…

预定2.0 Crack ZoomCharts JavaScript 最值得探索

世界上最可探索的 JavaScript 图表 将内容深入分析和支持多点触控的大数据可视化轻松集成到您的 Web 项目中--ZoomCharts JavaScript 快速、简单且令人印象深刻的 JavaScript 图表 以极快的速度将 javascript 图表与令人惊叹的向下钻取功能集成&#xff0c;一定会给您的团队、…

Word控件Spire.Doc 【文本】教程(22) ;在 Word 中应用强调标记(C#/VB.NET)

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

Live800:在线客服系统如何帮助企业创造持续的服务价值?

德鲁克管理箴言&#xff1a;企业的唯一目的就是“创造顾客”。 如何创造顾客&#xff1f;只能依靠产品和服务。产品和服务是连接企业与客户的天然纽带和必然桥梁。 企业依靠持续不断生产满足客户需求、符合客户价值主张的优质产品和服务来创造客户、留住客户并建立客户忠诚度…

视频怎么添加水印?快来收好这些方法

如今短视频行业发展得如火如荼&#xff0c;很多小伙伴都投入了短视频制作中。我最初发布视频只是因为热爱记录日常&#xff0c;顺便还能增进一下自己的视频剪辑水平。刚开始没想那么多&#xff0c;视频制作好就直接传到平台上去了&#xff0c;后来才发现自己的视频被别人搬运&a…

高通量筛选化合物库抑制缺氧诱导因子抑制剂

研究证明了土著细菌具有铁依赖性机制&#xff0c;可以抑制宿主铁的运输和储存。通过微生物代谢物的高通量筛选&#xff0c;研究人员发现&#xff0c;肠道菌群产生的代谢物能抑制肠道铁吸收主要转录因子低氧诱导因子 2α (HIF-2α)&#xff0c;并增加铁存储蛋白铁蛋白 (Ferritin…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.3 H2数据库

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.3 H2数据库4.3.1 问题引入4.3.2 内置数据库4.3.3 …

微信小程序使用npm教程

首先打开工具-详情-勾选使用npm模块 使用npm的步骤&#xff1a; 1. 安装 npm 包 在小程序 package.json 所在的目录中执行命令安装 npm 包&#xff1a; npm install此处要求参与构建 npm 的 package.json 需要在 project.config.json 定义的 miniprogramRoot 之内。 tips&am…

【大数据存储技术】思考题及参考答案

文章目录第1章 绪论1. NoSQL和关系型数据库在设计目标上有何主要区别&#xff1f;2. 简要总结一下NoSQL数据库的技术特点。第2章 NoSQL数据库的基本原理1. 描述分布式数据管理的特点。2. 什么是CAP原理&#xff1f;CAP原理是否适用于单机环境&#xff1f;3. 简述BASE理论的具体…