{"id":17072064,"url":"https://github.com/singgel/golang-base","last_synced_at":"2025-05-07T12:41:18.007Z","repository":{"id":105209571,"uuid":"480253655","full_name":"singgel/golang-base","owner":"singgel","description":"-   理解编译器的词法与语法解析、类型检查、中间代码生成以及机器码生成过程； -   理解数组、切片、哈希表和字符串等数据结构的内部表示以及常见操作的原理； -   理解 Go 语言中的函数、方法以及反射等语言特性； -   理解常见并发原语 `Mutex`、`WaitGroup` 以及扩展原语的使用和原理； -   理解 make、new、defer、select、for 和 range 等关键字的实现； -   理解运行时中的调度器、网络轮询器、内存分配器、垃圾收集器的实现原理； -   理解 HTTP、RPC、JSON 等标准库的设计与原理；","archived":false,"fork":false,"pushed_at":"2022-05-16T08:44:28.000Z","size":251,"stargazers_count":3,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-31T10:04:48.203Z","etag":null,"topics":["channel","control","function","goroutine","interface","reflect","strconv","struct","sync"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/singgel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-11T06:27:08.000Z","updated_at":"2025-02-20T15:24:42.000Z","dependencies_parsed_at":"2023-03-23T02:46:37.548Z","dependency_job_id":null,"html_url":"https://github.com/singgel/golang-base","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singgel%2Fgolang-base","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singgel%2Fgolang-base/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singgel%2Fgolang-base/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singgel%2Fgolang-base/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/singgel","download_url":"https://codeload.github.com/singgel/golang-base/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252879452,"owners_count":21818799,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["channel","control","function","goroutine","interface","reflect","strconv","struct","sync"],"created_at":"2024-10-14T11:38:28.208Z","updated_at":"2025-05-07T12:41:17.985Z","avatar_url":"https://github.com/singgel.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# golang-base\n\n### liwenzhou个人博主学习站\n一个个人的学习站,博主在每一期都录制了视频  \nhttps://www.liwenzhou.com/archives/  \n[视频地址](https://www.bilibili.com/video/BV16E411H7og)  \n\n### 欧长坤 个人博主学习站  \nhttps://golang.design/  \n\n### 一个字节同学的个人博主学习站  \nGo 语言设计与实现的作者  \nhttps://draveness.me/golang/  \n\n-   理解编译器的词法与语法解析、类型检查、中间代码生成以及机器码生成过程；\n-   理解数组、切片、哈希表和字符串等数据结构的内部表示以及常见操作的原理；\n-   理解 Go 语言中的函数、方法以及反射等语言特性；\n-   理解常见并发原语 `Mutex`、`WaitGroup` 以及扩展原语的使用和原理；\n-   理解 make、new、defer、select、for 和 range 等关键字的实现；\n-   理解运行时中的调度器、网络轮询器、内存分配器、垃圾收集器的实现原理；\n-   理解 HTTP、RPC、JSON 等标准库的设计与原理；\n\n### 一个阿里同学的个人博主学习站  \nlianglianglee这个博主的知识面很宽而且在每个领域都有一定深度的认识，最起码文章上面写的不是流水账，很推荐  \nhttps://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/22%20%E8%AE%B2%E9%80%9A%E5%85%B3%20Go%20%E8%AF%AD%E8%A8%80-%E5%AE%8C  \n\n\n-12步通关求职面试-完\n-22 讲通关 Go 语言-完\n-24讲吃透分布式数据库-完\n-300分钟吃透分布式缓存-完\n-CNCF X 阿里巴巴云原生技术公开课\n-DDD 微服务落地实战\n-DDD实战课\n-Dubbo源码解读与实战-完\n-ElasticSearch知识体系详解\n-JVM 核心技术 32 讲（完）\n-Java 业务开发常见错误 100 例\n-Java 并发编程 78 讲-完\n-Java 性能优化实战-完\n-Java并发编程实战\n-Kafka核心技术与实战\n-Kubernetes 从上手到实践\n-Kubernetes 实践入门指南\n-MySQL实战45讲\n-MySQL实战宝典\n-Netty 核心原理剖析与 RPC 实践-完\n-OKR组织敏捷目标和绩效管理-完\n-Redis 核心原理与实战\n-RocketMQ 实战与进阶（完）\n-Serverless 技术公开课（完）\n-ShardingSphere 核心原理精讲-完\n-Spring Boot 实战开发\n-Spring Security 详解与实操\n-SpringCloud微服务实战（完）\n-ZooKeeper源码分析与实战-完\n-互联网消费金融高并发领域设计\n-全解网络协议\n-分布式中间件实践之路（完）\n-分布式技术原理与实战45讲-完\n-分布式链路追踪实战-完\n-前端工程化精讲-完\n-容器实战高手课\n-左耳听风\n-微服务质量保障 20 讲-完\n-架构设计面试精讲\n-案例上手 Spring Boot WebFlux（完）\n-消息队列高手课\n-深入剖析 MyBatis 核心原理-完\n-深入拆解Java虚拟机\n-深入浅出 Docker 技术栈实践课（完）\n-深入浅出 Java 虚拟机-完\n-深入浅出计算机组成原理\n-深入理解 Sentinel（完）\n-由浅入深吃透 Docker-完\n-白话设计模式 28 讲（完）\n-程序员的数学课\n-说透性能测试\n-软件工程之美\n-透视HTTP协议\n-重学操作系统-完\n-重学数据结构与算法-完\n-领域驱动设计实践（完）\n-高并发系统设计40问\n\n## 基础\n\n### slice 和map 声明, 初始化方式, 初始化 空切片和空map\n\n```\n// 声明切片类型\nvar name []T\n    var a []string              //声明一个字符串切片\n    var b = []int{}             //声明一个整型切片并初始化\n// 上面都是基于数组来创建的切片，如果需要动态的创建一个切片，我们就需要使用内置的make()函数\nmake([]T, size, cap)\n    s1 := make([]int, 3) //[0 0 0]\n\n// map格式定义\nmap[KeyType]ValueType\n// map类型的变量默认初始值为nil，需要使用make()函数来分配内存\nmake(map[KeyType]ValueType, [cap])\n    scoreMap := make(map[string]int, 8)\n    scoreMap[\"张三\"] = 90\n\n// slice遍历\n        for index, value := range s {\n                fmt.Println(index, value)\n        }        \n// map遍历\n        for k, v := range scoreMap {\n                fmt.Println(k, v)\n        }\n```\n\n### slice 和 map 的循环遍历(有兴趣可以了解为什么map循环无序)\n\n```\n源码：\n// decide where to start\nr := uintptr(fastrand())\n结果：\n因此每次重新 for range map，你见到的结果都是不一样的。那是因为它的起始位置根本就不固定！\n\n根本原因：\n你想问为什么要这么做？当然是官方有意为之，因为官方在 Go 早期的时候，发现很多工程师都较依赖 map 的遍历迭代顺序。但这将会导致可移植性存在问题。因此，改之。也请不要依赖...\n```\n\n-   ### append 实现两个slice 合并方式\n-   -   进阶可以了解 append 内存扩容机制,内存对齐情况下的扩容\n    -   声明cap的好处\n\n```\nGo语言的内建函数append()可以为切片动态添加元素。 可以一次添加一个元素，可以添加多个元素，也可以添加另一个切片中的元素（后面加…）。\n\nvar citySlice []string\n// 追加一个元素\ncitySlice = append(citySlice, \"北京\")\n// 追加多个元素\ncitySlice = append(citySlice, \"上海\", \"广州\", \"深圳\")\n// 追加切片\na := []string{\"成都\", \"重庆\"}\ncitySlice = append(citySlice, a...) // //[北京 上海 广州 深圳 成都 重庆]\n\n首先判断，如果新申请容量（cap）大于2倍的旧容量（old.cap），最终容量（newcap）就是新申请的容量（cap）。\n否则判断，如果旧切片的长度小于1024，则最终容量(newcap)就是旧容量(old.cap)的两倍，即（newcap=doublecap），\n否则判断，如果旧切片长度大于等于1024，则最终容量（newcap）从旧容量（old.cap）开始循环增加原来的1/4，即（newcap=old.cap,for {newcap += newcap/4}）直到最终容量（newcap）大于等于新申请的容量(cap)，即（newcap \u003e= cap）\n如果最终容量（cap）计算值溢出，则最终容量（cap）就是新申请容量（cap）。\n```\n\n### 结构体和结构体方法使用\n\n```\n类型别名规定：TypeAlias只是Type的别名，本质上TypeAlias与Type是同一个类型。\n\n//类型定义\ntype NewInt int\n//类型别名\ntype MyInt = int\n\n使用type和struct关键字来定义结构体，结构体本身也是一种类型，我们可以像声明内置类型一样使用var关键字声明结构体类型。\ntype person struct {\n        name string\n        city string\n        age  int8\n}\n在定义一些临时数据结构等场景下还可以使用匿名结构体\n使用new关键字对结构体进行实例化，方法定义格式，接收者的概念就类似于其他语言中的this或者 self，方法与函数的区别是，函数不属于任何类型，方法属于特定的类型。\nfunc (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {\n    函数体\n}\n结构体中字段大写开头表示可公开访问，小写表示私有（仅在定义当前结构体的包中可访问）。\n```\n\n### struct 和 json 之间转换(tag使用, omitempty 使用)\n\n```\n//JSON序列化：结构体--\u003eJSON格式的字符串\ndata, err := json.Marshal(c)\nif err != nil {\n        fmt.Println(\"json marshal failed\")\n        return\n}\n\n//JSON反序列化：JSON格式的字符串--\u003e结构体\nstr := `{\"Title\":\"101\",\"Students\":[{\"ID\":0,\"Gender\":\"男\",\"Name\":\"stu00\"},{\"ID\":1,\"Gender\":\"男\",\"Name\":\"stu01\"},{\"ID\":2,\"Gender\":\"男\",\"Name\":\"stu02\"}]}`\nc1 := \u0026Class{}\nerr = json.Unmarshal([]byte(str), c1)\n\nTag是结构体的元信息，可以在运行的时候通过反射的机制读取出来。 Tag在结构体字段的后方定义，由一对反引号包裹起来，具体的格式如下：\n`key1:\"value1\" key2:\"value2\"`\n//Student 学生\ntype Student struct {\n        ID     int    `json:\"id\"` //通过指定tag实现json序列化该字段时的key\n        Gender string //json序列化是默认使用字段名作为key\n        name   string //私有不能被json包访问\n}\n如果想要在序列序列化时忽略这些没有值的字段时，可以在对应字段添加omitempty tag。对象、引用和零值用指针可以破解\ntype Dog struct {\n        Breed    string\n        // dog的weight是未知，而不是0,并不是我们想要的结果\n        WeightKg int `json:\",omitempty\"`\n}\n```\n\n-   ### 了解go的控制结构\n-   -   if-else\n    -   for\n    -   switch\n    -   goto\n    -   break\n    -   continue\n\n```\nif 表达式1 {\n    分支1\n} else if 表达式2 {\n    分支2\n} else{\n    分支3\n}\n// for循环可以通过break、goto、return、panic语句强制退出循环。\nfor 初始语句;条件表达式;结束语句{\n    循环体语句\n}\nGo语言中可以使用for range遍历数组、切片、字符串、map 及通道（channel）。 通过for range遍历的返回值有以下规律：\n    数组、切片、字符串返回索引和值。\n    map返回键和值。\n    通道（channel）只返回通道内的值。\n// fallthrough语法可以执行满足条件的case的下一个case，是为了兼容C语言中的case设计的。\nfunc switchDemo5() {\n        s := \"a\"\n        switch {\n        case s == \"a\":\n                fmt.Println(\"a\")\n                fallthrough\n        case s == \"b\":\n                fmt.Println(\"b\")\n        case s == \"c\":\n                fmt.Println(\"c\")\n        default:\n                fmt.Println(\"...\")\n        }\n}\n// goto语句通过标签进行代码间的无条件跳转。goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto语句能简化一些代码的实现过程。\nfunc gotoDemo2() {\n        for i := 0; i \u003c 10; i++ {\n                for j := 0; j \u003c 10; j++ {\n                        if j == 2 {\n                                // 设置退出标签\n                                goto breakTag\n                        }\n                        fmt.Printf(\"%v-%v\\n\", i, j)\n                }\n        }\n        return\n        // 标签\nbreakTag:\n        fmt.Println(\"结束for循环\")\n}\n\nbreak语句可以结束for、switch和select的代码块。\ncontinue语句可以结束当前循环，开始下一次的循环迭代过程，仅限在for循环内使用。\n```\n\n### func 参数传递和实现不定参数的方法\n\n```\nfunc 函数名(参数)(返回值){\n    函数体\n}\n\n函数可以作为类型、变量、参数、返回值\n\n// 匿名函数\nfunc(参数)(返回值){\n    函数体\n}\n// 闭包\nfunc adder() func(int) int {\n        var x int\n        return func(y int) int {\n                x += y\n                return x\n        }\n}\nfunc main() {\n        var f = adder()\n        fmt.Println(f(10)) //10\n        fmt.Println(f(20)) //30\n        fmt.Println(f(30)) //60\n}\n```\n\n### interface接口定义和使用场景\n\n```\ntype 接口类型名 interface{\n    方法名1( 参数列表1 ) 返回值列表1\n    方法名2( 参数列表2 ) 返回值列表2\n    …\n}\n```\n\n### defer 方法使用及场景\n\n```\nGo语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时，将延迟处理的语句按defer定义的逆序进行执行，也就是说，先被defer的语句最后被执行，最后被defer的语句，最先被执行。\n由于defer语句延迟调用的特性，所以defer语句能非常方便的处理资源释放问题。比如：资源清理、文件关闭、解锁及记录时间等。\n在Go语言的函数中return语句在底层并不是原子操作，它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后，RET指令执行前。\n\nrecover()必须搭配defer使用。\ndefer一定要在可能引发panic的语句之前定义。\n```\n\n### _, ok 模式的使用场景\n\n```\n我们在使用Golang编程时，经常会使用到Golang比较特殊的一种写法，即：\", OK\"\n使用场景：在一个表达式返回2个参数的时候使用，第一个参数是一个值或者nil，第二个参数是true/false或者一个错误error\n在一个需要赋值的if条件语句中，使用这种模式去检测第二个参数值会让代码显得优雅简洁。\n\n在函数返回时检测错误\n检测映射中是否存在一个键值\n检测一个接口类型变量 varI 是否包含了类型 T：类型断言\n检测一个通道 ch 是否关闭\n```\n\n-   ### 使用go实现发送如下请求到接口,并把结果解析到对应结构体\n-   -   GET 访问接口https://httpbin.org/get\n    -   POST form 表单请求到接口 https://httpbin.org/post\n    -   POST body json 请求到接口https://httpbin.org/post\n    -     思考: 以上请求如何添加超时时间设置\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinggel%2Fgolang-base","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsinggel%2Fgolang-base","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinggel%2Fgolang-base/lists"}