Golang
文章平均质量分 76
Chasel_H
记录学习
展开
-
分布式链路追踪实战篇-日志库集成opentelemetry的思路
由上文可以知道分布式链路追踪的作用,但是距离应用到项目中,我们还需要对项目中一些关键组件进行opentelemetry的集成,例如日志库,ORM、http框架、rpc框架等。原创 2023-11-24 16:18:11 · 1319 阅读 · 2 评论 -
分布式链路追踪入门篇-基础原理与快速应用
链路追踪(Distributed Tracing)是一种用于监测和诊断分布式应用程序中请求路径的技术。在分布式系统中,单个请求可能会涉及多个服务和组件。链路追踪通过记录和分析请求在这些服务之间的传递路径和执行情况,帮助开发人员和运维团队理解系统的运行状况、性能和问题。Span(片段): 在链路追踪中,Span 是描述单个操作或事件的基本单元。一个请求被分解成一个或多个 Span,每个 Span 表示一个操作的开始和结束。例如,一个数据库查询、一个 HTTP 请求、一个函数调用等都可以作为一个 Span。原创 2023-11-23 11:58:30 · 1065 阅读 · 0 评论 -
golang下载自定义excel模板
主要是使用第三方的tealeg/xlsx包来生成excel文件package mainimport ( "bytes" "fmt" "github.com/gin-gonic/gin" "github.com/tealeg/xlsx" "net/http")type RowData struct { UserName string Age int StuId int}func FileDownload(c *gin.Context) { file := xlsx.NewF原创 2021-04-21 14:34:36 · 574 阅读 · 0 评论 -
Go的内存分配(一)
本文仅自己阅读笔记,详细请阅读原文draveness-内存分配器一、概述程序中的数据和变量都会被分配到程序所在的虚拟内存中,内存空间包含两个重要区域:栈区(Stack)和堆区(Heap)。不同的编程语言会选择不同的方式管理内存,而在Go语言中管理方式如下:栈区由编译器管理:其中函数调用的参数、返回值以及局部变量大都会被分配到栈上,这部分内存会由编译器进行管理;堆中的对象由内存分配器分配并由垃圾收集器回收。二、内存分配器内存管理一般包含三个不同的组件:用户程序、分配器和收集器,而当用户程序申原创 2021-03-11 23:58:56 · 781 阅读 · 1 评论 -
Golang的内存逃逸分析
1、什么是逃逸分析?逃逸分析是一种确定指针动态范围的方法,可以分析在程序的哪些地方可以访问到指针。逃逸分析做了什么?Go是通过在编译期间通过编译器来进行逃逸分析,决定一个变量是放堆上还是栈上。其规则如下:变量没有...原创 2021-03-05 21:49:11 · 551 阅读 · 0 评论 -
细说Golang的反射
一、什么是反射?Go 语言提供了一种机制在运行时更新变量和检查它们的值、调用它们的方法,但是在编译时并不知道这些变量的具体类型,这称为反射机制。二、为什么要用反射?以下是需要反射的 2 个常见场景:有时你需要编写一个函数,但是并不知道传给你的参数类型是什么,可能是没约定好;也可能是传入的类型很多,这些类型并不能统一表示。这时反射就会用的上了有时候需要根据某些条件决定调用哪个函数,比如根据用户的输入来决定。这时就需要对函数和函数的参数进行反射,在运行期间动态地执行函数。三、反射是如何实原创 2021-01-12 23:00:10 · 1486 阅读 · 0 评论 -
net/http源码分析之Go原生是如何搭建web程序
Go原生代码库实现一个简单的web程序以下实现了一个简单的web实例示例代码:package mainimport ( "fmt" "net/http")func handler(w http.ResponseWriter, r *http.Request) { //r.URL.Path是请求URL的路径部分 //其尾随的[1:]意思是“创建Path中第一个字符到结尾的子片段”(这将从路径名中删除前导“ /”)。 //将format字符串写入w fmt.Fpri原创 2021-01-07 20:15:44 · 291 阅读 · 0 评论 -
Go-select语句详解
1、什么是select语句?select 是 Go 中的一个控制结构。select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。2、select语句的作用?当我们需要同时从多个通道接收数据时,如果通道里没有数据将会发生阻塞。为了应对这种场景,Go内置了select关键字,可以同时响应多个通道的操作。3、select语句的语法结构select { case 表达式1: state原创 2021-01-06 16:05:43 · 1500 阅读 · 0 评论 -
Go协程间的通信
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、概念我们知道协程是独立执行的,他们之间没有通信。协程间必须通过通信协调/同步他们的工作。1、协程间通过通道(channel)来通信协程可以使用共享变量来通信,但是在Go中并不提倡这样做,因为这种方式给所有的共享内存的多线程都带来了困难。而Go是通过一种特殊的类型,通道(channel),一个可以用于发送类型化数据的管道,由其负责协程之间的通信,从而避开所有由共享内存导致的陷阱;这种通过通道进行通信的方式保证了同步原创 2020-12-24 20:42:41 · 3992 阅读 · 1 评论 -
Go协程
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、什么是协程?1、进程和多线程一个应用程序是运行在机器上的一个进程;进程是一个运行在自己内存地址空间里的独立执行体。一个进程由一个或多个操作系统线程组成,这些线程其实是共享同一个内存地址空间的一起工作的执行体。几乎所有’正式’的程序都是多线程的,以便让用户或计算机不必等待,或者能够同时服务多个请求或增加性能和吞吐量。2、多线程的缺点因为在一个进程里的多个线程是共享内存的,意味着在多线程应用中内存中的数据是被多个原创 2020-12-24 14:25:31 · 454 阅读 · 2 评论 -
Go-通过sync包实现锁机制
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、锁为什么要使用锁?为了避免发生一个变量在多个线程被使用或修改,而导致我们无法预知被不同线程修改的程序。锁怎么解决问题?一次只能让一个线程对共享变量进行操作。当变量被一个线程改变时,我们为它上锁,直到这个线程执行完成并解锁后,其他线程才能访问它。二、sync包中的锁在 Go 中这种锁的机制是通过 sync 包中 Mutex 来实现的。sync.Mutex 是一个互斥锁,它的作用是守护在临界区入口来确原创 2020-12-22 15:05:03 · 232 阅读 · 1 评论 -
Go的错误处理
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、错误处理Go 有一个预先定义的 error 接口类型:type error interface { Error() string}1、定义错误当你需要一个新的错误类型,都可以用 errors(必须先 import)包的 errors.New 函数接收合适的错误信息来创建,像下面这样:err := errors.New("math - square root of negative number")例如:原创 2020-12-22 13:17:33 · 1415 阅读 · 0 评论 -
Go的接口
加粗样式本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、什么是接口?目前为止,我们看到的类型都是具体的类型,一个具体的类型可以准确的描述它所代表的值。而接口类型是一种抽象的类型。它不会暴露出它所代表的对象的内部值的结构和这个对象支持的基础操作的集合;它们只会表现出它们自己的方法。也就是说当你有看到一个接口类型的值时,你不知道它是什么,唯一知道的就是可以通过它的方法来做什么。接口的定义格式:type Namer interface { Method1(p原创 2020-12-16 18:47:42 · 92 阅读 · 0 评论 -
Go的垃圾回收
Go 开发者不需要写代码来释放程序中不再使用的变量和结构占用的内存,在 Go 运行时中有一个独立的进程,即垃圾收集器(GC),会处理这些事情,它搜索不再使用的变量然后释放它们的内存。显式触发GC可以通过 runtime 包访问 GC 进程。通过调用 runtime.GC() 函数可以显式的触发 GC,但这只在某些罕见的场景下才有用,比如当内存资源不足时调用 runtime.GC(),它会在此函数执行的点上立即释放一大片内存,此时程序可能会有短时的性能下降(因为 GC 进程在执行)。如何知道当前的内.原创 2020-12-16 13:30:07 · 224 阅读 · 0 评论 -
Go方法——一种特殊类型的函数
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、方法是什么Go 方法是作用在接收者上的一个函数,接收者是某种类型的变量。类似于面向对象中类的方法。接收者类型可以是(几乎)任何类型,不仅仅是结构体类型:任何类型都可以有方法,甚至可以是函数类型,可以是 int、bool、string 或数组的别名类型。(ps:接收者是接收者类型的变量)1、方法的定义与调用定义方法的一般格式如下:func (recv receiver_type) methodName(para原创 2020-12-16 13:10:16 · 334 阅读 · 0 评论 -
Go中类型的String方法
在Go中,当类型实现了String方法时,调用格式化输出函数输出类型变量会自动调用该类型的String方法下面主要介绍当一个类型有无实现String()方法以及String方法的接收者类型为指针类型还是值类型时,打印类型实例的的区别:1、没实现String方法示例:package mainimport "fmt"type Person struct { name string height string}//func (p *Person)String() string{// .原创 2020-12-16 12:51:05 · 2073 阅读 · 0 评论 -
Go结构体
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、结构体定义结构体定义的一般方式如下:type identifier struct { field1 type1 //字段名1 数据类型 field2 type2 //字段名2 数据类型 ...}结构体的字段可以是任何类型,甚至是结构体本身,也可以是函数或者接口。1、使用 new与使用var声明结构体的区别使用 new 函数给一个新的结构体变量分配内存,它返回指向原创 2020-12-13 19:56:37 · 203 阅读 · 0 评论 -
Go的map
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、map的声明、赋值、初始化和make1、map的介绍map 是引用类型,可以使用如下声明:var map1 map[keytype]valuetype1、在声明的时候不需要知道 map 的长度,map 是可以动态增长的。2、常用的 len(map1) 方法可以获得 map 中的 pair 数目,这个数目是可以伸缩的,因为 map-pairs 在运行时可以动态添加和删除。3、未初始化的 map 的值是 nil原创 2020-12-12 16:49:26 · 231 阅读 · 0 评论 -
Go字符串、数组和切片的应用
一、从字符串生成字节切片假设 s 是一个字符串(本质上是一个字节数组),那么就可以直接通过 c := []byte(s) 来获取一个字节的切片 c。另外,您还可以通过 copy 函数来达到相同的目的:copy(dst []byte, src string)。您还可以将一个字符串追加到某一个字节切片的尾部:var b []bytevar s stringb = append(b, s…)二、获取字符串的某一部分使用 substr := str[start:end] 可以从字符串 str原创 2020-12-12 15:27:08 · 724 阅读 · 1 评论 -
Go切片
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、切片的介绍切片(slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型。这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集。需要注意的是,终止索引标识的项不包括在切片内。切片提供了一个相关数组的动态窗口。1、和数组不同的是,切片的长度可以在运行时修改,最小为 0 最大为相关数组的长度:切片是一个长度可变的数组。2、多个切片如果表示同一个数组的片段原创 2020-12-10 18:39:06 · 288 阅读 · 0 评论 -
Go数组
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、数组的简介数组是具有相同唯一类型 的一组已编号且长度固定的数据项序列。这种类型可以是任意的原始类型例如整型、字符串或者自定义类型数组长度必须是一个常量表达式,并且必须是一个非负整数。数组长度也是数组类型的一部分,所以[5]int和[10]int是属于不同类型的。数组的编译时值初始化是按照数组顺序完成的。数组元素可以通过 索引(位置)来读取(或者修改),索引从 0 开始。二、数组的声明var identi原创 2020-12-10 16:18:55 · 93 阅读 · 0 评论 -
Go函数(四)之闭包
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、匿名函数当我们不希望给函数起名字的时候,可以使用匿名函数。例如:func(x, y int) int { return x + y }。这样的一个函数不能够独立存在(编译器会返回错误:non-declaration statement outside function body)但可以被赋值于某个变量,即保存函数的地址到变量中:fplus := func(x, y int) int { return x + y }原创 2020-12-09 17:47:12 · 94 阅读 · 0 评论 -
Go函数(三)之回调函数
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go函数可以作为其它函数的参数进行传递,然后在其它函数内调用执行,一般称之为回调。package mainimport ( "fmt")func main() { callback(1, Add)}func Add(a, b int) { fmt.Printf("The sum of %d and %d is: %d\n", a, b, a+b)}func callback(y int, f func原创 2020-12-09 16:42:16 · 1319 阅读 · 0 评论 -
Go函数(二)之defer实现代码追踪
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go关键字 defer 允许我们推迟到函数返回之前一刻或任意位置执行 return 语句之后才执行某个语句或函数。为什么要在返回之后才执行这些语句?因为 return 语句同样可以包含一些操作,而不是单纯地返回某个值package mainimport "fmt"func main() { function1()}func function1() { fmt.Printf("In function1 at t原创 2020-12-09 16:33:55 · 162 阅读 · 0 评论 -
Go函数(一)
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、函数的介绍1、函数每一个程序都包含很多的函数:函数是基本的代码块。Go是编译型语言,所以函数编写的顺序是无关紧要的Go 里面有三种类型的函数:- 普通的带有名字的函数- 匿名函数或者lambda函数- 方法除了main()、init()函数外,其它所有类型的函数都可以有参数与返回值。函数参数、返回值以及它们的类型被统称为函数签名。2、函数调用函数被调用的基本格式如下:pack1.Function(原创 2020-12-08 14:25:49 · 144 阅读 · 0 评论 -
Go控制结构
我们看到的Go程序都是从main函数开始执行,然后顺序执行该函数体中的代码。但是我们很多时候都需要在代码里进行条件判断。一、if-else结构if 是用于测试某个条件(布尔型或逻辑型)的语句,如果该条件成立,则会执行 if 后由大括号括起来的代码块,否则就忽略该代码块继续执行后续的代码。if condition { // do something }如果存在第二个分支,则可以在上面代码的基础上添加 else 关键字以及另一代码块,这个代码块中的代码只有在条件不满足时才会执行。if condi原创 2020-12-07 18:23:59 · 125 阅读 · 0 评论 -
Go的中字符串常用的API
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go作为一种基本数据结构,每种语言都有一些对于字符串的预定义处理函数。Go 中使用 strings 包来完成对字符串的主要操作。1、前缀和后缀HasPrefix 判断字符串 s 是否以 prefix 开头:strings.HasPrefix(s, prefix string) boolHasSuffix 判断字符串 s 是否以 suffix 结尾:strings.HasSuffix(s, suffix string)原创 2020-12-04 15:38:05 · 442 阅读 · 0 评论 -
Go变量
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、变量的简介1、变量的声明声明变量的一般形式是使用 var 关键字:var identifier type当一个变量被声明之后,系统自动赋予它该类型的零值:int 为 0,float 为 0.0,bool 为 false,string 为空字符串,指针为 nil。记住,所有的内存在 Go 中都是经过初始化的。2、变量的作用域一个变量(常量、类型或函数)在程序中都有一定的作用范围,称之为作用域。全局变量:如果原创 2020-12-03 19:10:04 · 88 阅读 · 0 评论 -
Go常量
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go常量使用关键字 const 定义,用于存储不会改变的数据。存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。常量的值必须是能够在编译时就能够确定的;你可以在其赋值表达式中涉及计算过程,但是所有用于计算的值必须在编译期间就能获得。正确的做法:const c1 = 2/3错误的做法:const c2 = getNumber() // 引发构建错误: getNumber() used as v原创 2020-12-03 19:10:40 · 341 阅读 · 0 评论 -
Go程序的一般结构和程序的执行顺序
如下面示例程序所示,一般总体思路如下:在完成包的 import 之后,开始对常量、变量和类型的定义或声明。如果存在 init 函数的话,则对该函数进行定义(这是一个特殊的函数,每个含有该函数的包都会首先执行这个函数)。如果当前包是 main 包,则定义 main 函数。然后定义其余的函数,首先是类型的方法,接着是按照 main 函数中先后调用的顺序来定义相关函数,如果有很多函数,则可以按照字母顺序来进行排序。示例程序:package mainimport ( "fmt")c原创 2020-12-03 15:35:31 · 297 阅读 · 0 评论