Golang
潘广宇
主攻Golang|Python|PHP|数据库|高并发架构|人工智能,Base广州,博客主要写一些工作上遇到的问题和处理经验
展开
-
Golang 手把手搭建一个简单的 gRPC 服务
注意项:gRPC 和标准库的 RPC 框架有一个区别,gRPC 生成的接口并不支持异步调用。不过可以在多个 Goroutine 之间安全地共享 gRPC 底层的 HTTP/2 连接,因此可以通过在另一个 Goroutine 阻塞调用的方式模拟异步调用。2、安装 protoc-gen-go-grpc,安装方式参考上述文章提到的 protoc-gen-go 安装方式。原创 2024-04-10 16:55:32 · 625 阅读 · 0 评论 -
Golang ProtoBuf 初学者完整教程:语法
7、RPC 服务名和方法名,均使用首字母大写驼峰风格,例如service FooService{ rpc GetSomething() }4、消息名使用首字母大写驼峰风格(CamelCase),例如message StudentRequest { ... }1、文件名使用小写下划线的命名风格,例如 lower_snake_case.proto。5、字段名使用小写下划线的风格,例如 string status_code = 1。6、枚举类型,枚举名使用首字母大写驼峰风格,例如 enum FooBar。原创 2024-04-10 14:02:08 · 1051 阅读 · 0 评论 -
Golang ProtoBuf 初学者完整教程:安装
Protobuf 在 .proto 定义需要处理的结构化数据,可以通过 protoc 工具,将 .proto 文件转换为 C、C++、Golang、Java、Python 等多种语言的代码。需要安装protoc-gen-go.exe可执行文件,当protoc命令执行时,当编译器调用时传递了 --go_out命令行标志时, protoc就会使用它。1、安装protoc:https://github.com/protocolbuffers/protobuf/releases。原创 2024-04-10 11:27:54 · 981 阅读 · 0 评论 -
Golang 实现一个简单的 RPC 服务
分享一个简单的 rpc 服务框架。原创 2024-04-09 20:58:56 · 610 阅读 · 0 评论 -
手把手教你搭建基于 Go kit 的 Http 微服务
实现一个简单的功能:通过http请求用户的uid,返回用户uid对应的name,age和level。Endpoint层主要负责Request/Response格式的转换,以及公用拦截器相关的逻辑。Transport层主要负责与传输协议HTTP,GRPC,THRIFT等相关的逻辑。Service层则专注于业务逻辑,就是我们的业务类、接口等相关信息存放。原创 2024-04-09 15:09:02 · 730 阅读 · 0 评论 -
Golang 为什么要使用接口
因为json、CSV都有一个步骤,就是读取,这样可以把这个步骤抽象出来(都属于一种Reader类型),这样就可以写出更方便和更通用的函数。上面这个例子中,重点关注的是 processFile 这个函数,它实现了不管什么类型(json、CSV)的文件,都可以处理。下面举一个例子,比如我想实现一个通用的函数,能够支持json、CSV文件的读取。这说明接口一个很重要的特点就是抽象,把不同类型的相同特点进行抽象统一。一个类型如果拥有一个接口需要的所有方法,那么这个类型就实现了这个接口。原创 2024-04-08 20:36:33 · 384 阅读 · 0 评论 -
Golang 为什么需要用反射
比如现在我想实现一个通用的db插入函数,支持我传入所有类型的struct,每一种类型的struct是一个单独的表,以struct的名称作为表名,然后插入到不同的表中。本质上是可以动态获取程序运行时的变量(类型)原创 2024-04-08 20:00:39 · 454 阅读 · 0 评论 -
Golang sync.Once 的作用
sync.Once的作用正是为了防止在多goroutine并发执行时,对某个操作进行重复的初始化。它确保即使在高度并发的场景下,某些高成本的初始化操作(比如创建资源、加载配置、设置全局状态等)也只会被执行一次。原创 2024-04-08 19:09:52 · 477 阅读 · 0 评论 -
Golang 基于共享变量的并发锁
原理:RWMutex允许多个goroutine同时获取读锁(RLock),进行并发读操作,而写锁(Lock)则是互斥的,同一时间只允许一个goroutine进行写操作。这意味着,一旦有goroutine开始写操作,其他想要读取或写入的goroutine都必须等待,直到写操作完成并且写锁被释放。RWMutex,即读写互斥锁,适用于读操作远远多于写操作的场景,当多个goroutine需要频繁地读取某个共享资源,而写入操作相对较少时,使用RWMutex可以提高并发性能。原创 2024-04-08 16:45:59 · 981 阅读 · 0 评论 -
理解 Golang 变量在内存分配中的规则
堆:大的局部变量,函数内部产生逃逸的变量,动态分配的数据,全局变量和静态变量。为什么有些变量在堆中分配、有些却在栈中分配?栈:函数局部变量,小数据。原创 2024-04-07 14:44:49 · 527 阅读 · 0 评论 -
Golang 创建一个简单的内存池
内存池主要作用是减少内存分配和释放的开销,提高程序的性能和效率。这样,当程序需要分配内存时,可以直接从内存池中获取一块已经分配好的内存,而不是每次都从操作系统申请新的内存。内存池可以设计为线程安全的,这样在多线程或多Goroutine的环境中,可以并发地从内存池中分配和释放内存,而不需要额外的同步操作。通过减少内存分配和释放的次数,内存池有助于降低垃圾回收器的工作负担,从而提高程序的运行效率。内存池可以减少内存碎片,因为内存池中的内存块是预先分配的,这样可以更有效地利用内存。原创 2024-04-07 14:00:54 · 533 阅读 · 0 评论 -
为什么要在 Golang 中使用指针
相反,你可以使用指针来传递文件内容的引用,这样可以避免复制整个文件内容,并允许多个 Goroutines 同时处理同一个文件。当你有一个大型的数据结构时,如果直接传递这个数据结构,会产生一个完整的副本,这会增加内存的使用和CPU的计算时间。使用指针,你可以只传递数据的地址,这样函数就可以直接在原始数据上操作,避免了复制的开销。如果你希望函数的修改反映到原始变量上,你需要传递变量的指针,这样函数就可以直接修改原始数据。如果你直接传递配置对象,那么函数内部修改的是对象的副本,并不会影响原始的全局配置。原创 2024-04-07 11:44:04 · 701 阅读 · 0 评论 -
Golang 方法的接收器 receiver 指针和值的区别
在 Go 语言中,如果一个方法的 receiver 是某个类型的指针,那么该类型的值和指针都可以调用这个方法。这是因为当 receiver 是指针类型时,Go 会自动进行指针解引用,以便让你方便地对这个类型的值进行操作。incr 方法的 receiver 是 Count 类型的指针。因此,既可以使用 Count 类型的值,也可以使用指向 Count 类型的指针来调用 incr 方法。原创 2024-03-07 10:55:16 · 493 阅读 · 0 评论 -
Golang 写日志到文件
os.O_EXCL: 与O_CREATE一起使用时,要求文件必须是新创建的,如果文件已经存在则返回错误。os.O_TRUNC: 如果可能,打开文件时先将文件内容清空。os.O_CREATE: 如果文件不存在则创建新文件。os.O_RDONLY: 以只读方式打开文件。os.O_WRONLY: 以只写方式打开文件。os.O_APPEND: 在文件末尾追加数据。os.O_SYNC: 打开文件用于同步I/O。os.O_RDWR: 以读写方式打开文件。原创 2024-03-07 09:38:34 · 779 阅读 · 0 评论 -
Golang 常用的时间转换
注意,这个时间2006-01-02 15:04:05完全不能改,是一个固定的时间(我不理解)Go 1.20之后增加的三个常量。原创 2024-03-06 15:38:14 · 918 阅读 · 0 评论 -
什么是 Golang 类型断言
在这里,areaIntf被赋值为sq1,而sq1是一个*Square类型的指针。因此,areaIntf包含了*Square类型的值,所以类型断言(areaIntf.(*Square))会返回一个非nil的*Square类型的指针,并且ok的值为true,表示类型断言成功。在Go语言中,类型断言返回两个值:转换后的值和一个布尔值,表示转换是否成功。类型断言:用于检查某个接口是否包含某个具体类型,语法x.(T),x是一个接口类型表达式,T是具体的类型,如果x包含的值可以被转换成T类型,则是ok。原创 2024-03-06 14:09:51 · 373 阅读 · 0 评论 -
Golang pprof 分析程序的使用内存和执行时间
也是可以通过 top 和 list 某个函数步骤去查看具体信息。-alloc_space:查看分配空间相关的信息。-inuse_space:查看当前内存使用情况。原创 2024-03-04 19:34:54 · 1659 阅读 · 0 评论 -
Golang 获取协程ID的方式
在协程执行函数里面,通过调用。原创 2024-03-04 15:12:34 · 419 阅读 · 0 评论 -
Golang Ants 构建协程池
2、当任务数大于协程数时,一个协程可以同时处理多个任务。3、监控是哪个协程ID处理了具体的任务。1、限制协程池里开启的协程数量。原创 2024-03-04 15:09:07 · 683 阅读 · 0 评论 -
Golang 函数中 defer 和 return 的调用顺序
2)关键字 defer 允许我们推迟到函数返回之前(或任意位置执行 return 语句之后)一刻才执行某个语句或函数。2)在函数最后返回前,执行defer()操作,对ret进行+1操作,这时候ret=10。2)在函数最后返回前,执行defer()操作,对ret进行+1操作,这时候ret=2。1) 函数先是执行到return 1,然后根据函数的声明,把1赋值给ret。1) 函数先是执行到return 9,然后根据函数的声明,把9赋值给ret。3)函数最终返回ret,所以2被main()所打印。原创 2024-02-29 20:39:52 · 363 阅读 · 0 评论 -
Golang 关于 interface 接口的理解
因为 Redis 类型实现了 StorageManager 接口中定义的所有方法(记住,是所有方法都必须实现定义)。在Go语言中,如果一个类型包含了接口中定义的所有方法,那么该类型就隐式地实现了该接口。在这里,Redis 类型实现了 insertData 和 updateData 方法,因此它可以被当做 StorageManager 类型使用。原创 2024-02-26 19:31:04 · 502 阅读 · 0 评论 -
Golang 语法系列:结构体
以上面的Person为例子,其实是通过一个函数来返回一个结构体指针实现的。5)格式5:通过&运算符直接对结构体进行取地址操作,然后完成实例化。4)格式4:通过new()函数实例化。// name age字段可以省略。2)格式2:通过键值对声明。3)格式3:匿名结构体。结构体:相当于"类"原创 2024-02-21 14:19:37 · 528 阅读 · 0 评论 -
Golang 判断数组某个元素是否存在 (isset)
如,现在需要判断命令行是否传了参数,即os.Args[1] 是否存在如果使用下述的判断:package mainimport ( "fmt" "os")func main() { if os.Args[1] != "" { fmt.Println("aaa") } else { fmt.Println("bbb") } }会报错:index out ...原创 2019-04-30 10:35:33 · 39457 阅读 · 3 评论 -
Golang 计算程序执行时间
package mainimport ( "time")func main() { startTime := time.Now().UnixNano() /* 程序主体 */ endTime := time.Now().UnixNano() seconds:= float64((endTime - startTime) / 1e9) ...原创 2019-04-27 22:45:01 · 6881 阅读 · 0 评论 -
Golang 获取 datetime Y-m-d H:i:s 时间
date := time.Now().Format("2006-01-02 15:04:05")// 将返回现在的datetime 如 2019-04-27 22:37:23原创 2019-04-27 22:38:13 · 2689 阅读 · 0 评论 -
Golang 文件操作:创建并写入文件
创建文件时,应该先判断文件是否存在:https://blog.csdn.net/panguangyuu/article/details/89608860package mainimport ( "os")func main() { filename = "test.php" f, err := os.Create(filename) defer f.Clo...原创 2019-04-27 22:33:52 · 9598 阅读 · 1 评论 -
Golang 文件操作:简单判断文件是否存在
package mainimport ( "os")func main() { filename = "test.go" _, err := os.Stat(filename) // 通过获取文件信息进行判断 if err != nil { // 错误不为空,表示文件不存在 } else { ...原创 2019-04-27 22:30:00 · 1998 阅读 · 0 评论 -
Golang 执行参数不限的 Linux 命令
package mainimport ( "os/exec")func main() { cmd := exec.Command("/bin/bash", "-c", "ls ...") // execContent, execErr := exec.Command("/bin/bash", "-c", "ls ...").Output()}原创 2019-04-27 22:27:22 · 505 阅读 · 0 评论 -
Golang 文件操作:一次性读取文件内容
Golang 逐行读取文件内容请看:https://blog.csdn.net/panguangyuu/article/details/89578417package mainimport ( "fmt" "io/ioutil")func main() { bytes, err := ioutil.ReadFile("./test.conf") if...原创 2019-04-26 23:19:13 · 5991 阅读 · 0 评论 -
Golang 文件操作:逐行读取文件
package mainimport( "os" "bufio" "io" "fmt")func main() { // 测试读取文件 f, err := os.Open("./test.conf") if err != nil { fmt.Printf("error : %s", err) } ...原创 2019-04-26 23:13:06 · 1558 阅读 · 0 评论 -
Go 与 PHP 计算速度的简单对比
一、测试 Go 计算10000000000 个数的求和时间package mainimport ( "fmt" "time")func main() { var sum int64 = 0 var startTime int64 = time.Now().UnixNano() for i := 0...原创 2019-03-16 16:49:52 · 6323 阅读 · 5 评论 -
Golang 文件操作:追加内容到文件
package mainimport ( "os") func main() { f, err := os.OpenFile(fileName, os.O_WRONLY, 0644) if err != nil { // 打开文件失败处理 } else { content = "写入的文件内容" // 查找文件末尾的偏移量 n, _...原创 2019-04-27 22:51:42 · 10456 阅读 · 0 评论 -
Golang 文件操作:删除指定的文件
package mainimport "os"func main () { err := os.Remove(logFile) if err != nil { // 删除失败 } else { // 删除成功 }}原创 2019-04-27 22:57:08 · 33788 阅读 · 0 评论 -
Golang 字符串操作:字符串反转
package mainfunc reverseString(r []rune) string{ for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r)}原创 2019-04-28 10:45:41 · 1684 阅读 · 0 评论 -
Golang 实现函数的任意类型传参
package mainimport ( "fmt")func init() { fmt.Print("init")}func main() { test1("123") test1(1) test2("123",1, "324", 12)}// 实现传单个任何类型的参数func test1(v interface{}) { fmt.Println(v) ...原创 2019-04-29 15:53:59 · 6163 阅读 · 0 评论 -
Golang 获取变量的类型
package mainimport ( "fmt" "reflect")func main() { v1 := 1 v2 := "test" v3 := map[string]int { } fmt.Println(reflect.TypeOf(v1)) -- int fmt.Println(...原创 2019-04-29 13:55:01 · 2071 阅读 · 0 评论 -
Golang 判断当前系统是 Linux 还是 Windows
package mainimport ( "runtime" "fmt")func main() { sysType := runtime.GOOS if sysType == 'linux' { // LINUX系统 } if sysType == 'windows' { // windows系统 }}...原创 2019-04-29 09:33:50 · 17099 阅读 · 2 评论 -
Golang 函数返回值是匿名函数的一个例子
func Test(person string) (func() string) { return func() string { return ("Hello " + person) }}原创 2019-05-04 11:44:31 · 1746 阅读 · 0 评论 -
Golang return 函数返回值的问题
这个问题源于看了这篇文章:https://blog.csdn.net/u010824081/article/details/77960209首先,看一个函数返回值的问题package mainimport ( "fmt")func main() { fmt.Println(test())}func test() (a int) { a = 1 ...原创 2019-05-04 11:40:39 · 10204 阅读 · 1 评论 -
Golang 函数参数是匿名函数的简单例子
package mainimport ( "fmt")func main() { test(1, add)}func add(a int, b int) { fmt.Println(a + b)}func test(num int, fun func(int, int)) { num = num + 1 fun(num, num)}...原创 2019-05-04 10:49:50 · 1614 阅读 · 0 评论