最全golang超详细基础入门教程_golang教程,揭秘今年Golang春招面试必问问题有哪些

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

3.2 类型别名

Go语言中的类型别名就是为已存在的类型定义一个别名,使用type关键字来定义,语法为type TypeAlias = Type

类型别名是Go 1.9版本添加的新功能,主要用于解决代码升级、迁移中存在的类型兼容性问题;在C/C++语言中,代码重构升级可以使用宏快速定义新的一段代码,Go语言中没有选择加入宏,而是解决了重构中最麻烦的类型名变更问题1。

例如,定义一个整数类型的别名Age

type Age int

那么Age就是int类型的别名。以后凡是使用Age的地方,都可以使用int代替。

3.3 常量

在Go语言中,常量是一种不可变的值。常量是在编译时就确定且在运行时不能被修改的量。

常量可以是任何基本类型,如整数、浮点数、布尔值、字符串或常量表达式。

定义常量的语法如下:

const constantName = value

其中,constantName是常量的名称,遵循标识符命名规则;value是常量的值。

例如,定义一个整数类型的常量Pi并赋值为3.14:

const Pi = 3.14

常量在编译时会被计算,因此可以在编译期间进行类型检查和类型推断

3.4 控制流语句

在Go语言中,控制流语句用于控制程序的执行流程。以下是一些常用的控制流语句:

3.4.1 条件语句(if)

根据条件执行不同的代码块:

if condition {
    // 如果条件为真,执行这里的代码块
} else if condition2 {
    // 如果条件为假,检查条件2,如果条件2为真,执行这里的代码块
} else {
    // 如果条件和条件2都为假,执行这里的代码块
}
3.4.2 switch语句

根据不同的条件执行不同的代码块:

switch expression {
case value1:
    // 当expression等于value1时执行的代码块
case value2:
    // 当expression等于value2时执行的代码块
...
default:
    // 当expression不等于任何一个case值时执行的代码块
}
3.4.3 循环语句(for)

重复执行同一段代码:

for initialization; condition; post {
    // 执行循环体
}
3.4.4 无限循环语句(for without conditions)

无限循环,除非使用break语句跳出循环:

for {
    // 无限循环,除非使用break语句跳出循环
}
3.4.5 跳转语句(break)

用于跳出循环或switch语句:

break; // 跳出当前循环或switch语句
3.4.6 返回语句(return)

从函数中返回值:

return value; // 返回一个值给调用者
3.4.7 错误处理(defer)

延迟执行某些代码,通常用于资源清理:

defer func() {
    // 延迟执行的代码,通常用于资源清理操作
}()

Go语言中还有一些更详细的控制流语句,包括空语句(empty statement)、无限循环语句(infinite loop)、标签和goto语句。由于篇幅有限,不再一一列举,有兴趣可自行学习。

3.5 函数定义和调用

在Go语言中,函数是一种可重复使用的代码块,用于执行特定的任务。函数定义指定了函数的名称、参数和返回值,而函数调用则是执行函数的过程。

下面是一个简单的函数定义和调用的示例:

package main

import "fmt"

// 函数定义
func greet(name string) string {
    return "Hello, " + name + "!"
}

func main() {
    // 函数调用
    fmt.Println(greet("Alice"))
    fmt.Println(greet("Bob"))
}

在上面的代码中,我们定义了一个名为greet的函数,它接受一个字符串参数name,并返回一个带有问候语的字符串。在main函数中,我们通过调用greet函数并传递不同的参数来打印不同的问候语。

在函数定义中,函数的名称指定了函数的名称,参数列表指定了函数接受的输入参数的类型和名称,而返回值列表指定了函数返回值的类型和名称。函数的定义以关键字func开头,后面跟着函数名称、参数列表和返回值列表。

在函数调用中,我们使用函数名称加上参数列表的方式来执行函数。参数列表中的参数数量和类型必须与函数定义中的参数列表匹配。调用函数后,返回的结果可以直接使用,也可以通过变量接收。

**请注意:**在Go语言中,函数的定义可以出现在任何地方,但通常建议将函数定义放在package级别以下。同时,函数名称的命名应该具有描述性,以便于阅读和理解。

3.6 数组和切片

在Go语言中,数组和切片是常用的数据结构,它们有一些共同点和区别。

数组的定义方式如下:

var arr [n]type

其中,n表示数组的长度,type表示数组元素的类型。例如,定义一个包含5个整数的数组:

var arr [5]int

可以通过索引访问数组元素,例如:

arr[0] = 10
fmt.Println(arr[0]) // 输出:10

切片的定义方式如下:

var slice []type

其中,type表示切片元素的类型。切片是一个动态长度的序列,可以通过追加元素来扩展。例如,创建一个包含3个整数的切片:

var slice []int
slice = append(slice, 10, 20, 30)

可以通过索引访问切片元素,例如:

slice[0] = 10
fmt.Println(slice[0]) // 输出:10

数组和切片的区别在于动态性和长度。数组的长度是固定的,不能改变,而切片的长度可以动态增长。此外,切片还有一些内置的方法和操作,例如len()append()函数,这些方法在数组中不可用。

需要注意的是,切片在创建时可以指定初始容量,例如:

var slice []int = make([]int, 5, 10)

这将创建一个初始长度为5,容量为10的切片。当切片的容量不足以容纳更多的元素时,切片会自动扩容。

3.7 映射

在Go语言中,映射(Map)是一种无序的键值对集合。它使用一个哈希表实现,提供了一种将键映射到值的方式。

映射的定义方式如下:

var m map[keyType]valueType

其中,keyType表示键的类型,valueType表示值的类型。

以下是一个使用映射的示例:

package main

import "fmt"

func main() {
    // 创建一个映射
    m := make(map[string]int)

    // 添加键值对
    m["apple"] = 1
    m["banana"] = 2
    m["orange"] = 3

    // 访问映射的值
    fmt.Println(m["apple"]) // 输出:1

    // 删除映射中的键值对
    delete(m, "banana")

    // 遍历映射
    for key, value := range m {
        fmt.Println(key, value)
    }
}

在上述示例中,我们首先使用make函数创建了一个映射m,然后通过key来添加、访问和删除映射中的值。使用delete函数可以删除指定键值对。最后,使用range循环遍历映射并打印键值对。

3.8 结构体

Go语言中的结构体(struct)是一种自定义数据类型,可以将多个基本数据类型组合到一起形成一个自定义的复合数据类型。

结构体的定义语法如下:

type 结构体名称 struct {
    字段1 字段1类型
    字段2 字段2类型
    ...
}

结构体中的字段名必须唯一,每个字段对应一个成员变量。结构体的定义和使用方法类似于C++中的结构体。

下面是一个简单的示例:

package main

import "fmt"

// 定义结构体
type Person struct {
    Name string
    Age  int
}

func main() {
    // 声明结构体变量
    var p Person

    // 直接赋值
    p.Name = "Alice"
    p.Age = 20

    // 通过成员访问运算符访问结构体成员变量
    fmt.Println(p.Name) // 输出:Alice
    fmt.Println(p.Age)  // 输出:20
}

结构体可以定义在函数内部或函数外部,定义位置影响到结构体的访问范围。如果结构体定义在函数外面,结构体名称首字母是否大写影响到结构体是否能跨包访问。如果结构体能跨包访问,属性首字母是否大写影响到属性是否跨包访问。通过结构体可以封装多个变量,实现面向对象编程。

3.9 方法

在Go语言中,方法(method)是一种与特定类型关联的函数。它允许我们为自定义类型定义行为,并在该类型的实例上调用方法。

方法的定义使用func关键字,后面跟着方法名、接收者(receiver)和参数列表。方法的接收者是一个特殊的参数,它指定了该方法与哪个类型相关联。

方法的定义语法如下:

func (接收者类型) 方法名(参数列表) {
    // 方法的实现
}

其中,接收者类型表示与该方法关联的类型,可以是自定义类型或内置类型。方法名是方法的名称,可以自定义。参数列表表示方法的参数,可以是零个或多个,与方法实现的具体逻辑相关。

以下是一个示例,演示了如何在Go语言中定义和使用方法:

package main

import "fmt"

// 自定义类型 Person
type Person struct {
    name string
    age  int
}

// 为 Person 类型定义一个方法 SayHello
func (p Person) SayHello() {
    fmt.Println("Hello, my name is", p.name)
}

func main() {
    // 创建一个 Person 实例
    person := Person{name: "Alice", age: 25}

    // 调用 Person 类型的方法 SayHello
    person.SayHello() // 输出:Hello, my name is Alice
}

在上述示例中,我们定义了一个名为Person的自定义类型,它包含nameage两个字段。然后,我们为Person类型定义了一个方法SayHello,该方法用于输出问候信息。在main函数中,我们创建了一个Person类型的实例,并调用了其SayHello方法。

需要注意的是,如果方法的接收者类型是自定义类型,那么方法可以访问该类型的所有公共(public)字段和方法。如果方法的接收者类型是内置类型,那么方法只能访问该类型的公开(public)方法和字段。

3.10 并发编程
3.10.1 goroutine

在Go语言中,Goroutine是一种轻量级的线程,它是Go语言实现并发编程的关键部分。Goroutine比操作系统线程更轻量级,启动和销毁Goroutine的开销更小,因此可以更高效地处理并发任务。

Goroutine由Go运行时环境管理,可以在程序中创建和调度。通过使用关键字go,可以将一个函数或方法标记为Goroutine,从而使其在后台并发执行。

下面是一个简单的示例,展示了如何使用Goroutine:

package main

import (


![img](https://img-blog.csdnimg.cn/img_convert/76a2f550a0fa23227745246c2b7a6d50.png)
![img](https://img-blog.csdnimg.cn/img_convert/86aaa7483471be829f77bad39d7fdf18.png)
![img](https://img-blog.csdnimg.cn/img_convert/6ccff2222f6c462baf12f75264888917.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

建和调度。通过使用关键字`go`,可以将一个函数或方法标记为Goroutine,从而使其在后台并发执行。


    下面是一个简单的示例,展示了如何使用Goroutine:



package main

import (

[外链图片转存中…(img-rGEYxA17-1715556695914)]
[外链图片转存中…(img-EXZ8oaHE-1715556695914)]
[外链图片转存中…(img-N0v2Q6qH-1715556695914)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
个人学习golang笔记,从各种教程中总结而来,作为入门参考。目录如下 目录 1. 入门 1 1.1. Hello world 1 1.2. 命令行参数 2 2. 程序结构 3 2.1. 类型 4 2.1.1. 命名类型(named type)与未命名类型(unamed type) 4 2.1.2. 基础类型(underlying type) 4 2.1.3. 可赋值性 5 2.1.4. 类型方法集 6 2.1.5. 类型声明 6 2.2. 变量 8 2.2.1. 变量声明 8 2.2.2. 类型零值 12 2.2.3. 指针 13 2.3. 赋值 17 2.4. 包和文件 17 2.5. 作用域 18 2.6. 语句 19 2.7. 比较运算符 20 2.8. 类型转换 21 2.9. 控制流 23 2.9.1. If 23 2.9.2. Goto 24 2.9.3. For 25 2.9.4. Switch 25 2.9.5. break语句 31 2.9.6. Continue语句 31 3. 基础数据类型 31 3.1. golang类型 31 3.2. Numeric types 32 3.3. 字符串 33 3.3.1. 什么是字符串 33 3.3.2. 字符串底层概念 35 3.3.3. 获取每个字节 38 3.3.4. Rune 39 3.3.5. 字符串的 for range 循环 40 3.3.6. 用字节切片构造字符串 41 3.3.7. 用rune切片构造字符串 42 3.3.8. 字符串的长度 42 3.3.9. 字符串是不可变的 42 3.3.10. UTF8(go圣经) 43 3.4. 常量 45 3.4.1. 常量定义 45 3.4.2. 常量类型 46 3.4.3. Iota 46 4. 组合数据类型 47 4.1. 数组 47 4.1.1. 数组概述 47 4.1.2. 数组的声明 49 4.1.3. 数组的长度 50 4.1.4. 遍历数组 50 4.1.5. 多维数组 51 4.2. 切片 52 4.2.1. 什么是切片 52 4.2.2. 切片概述 55 4.2.3. 创建一个切片 55 4.2.4. 切片遍历 57 4.2.5. 切片的修改 58 4.2.6. 切片的长度和容量 60 4.2.7. 追加切片元素 62 4.2.8. 切片的函数传递 65 4.2.9. 多维切片 66 4.2.10. 内存优化 67 4.2.11. nil slice和empty slice 69 4.2.12. For range 70 4.3. 结构 71 4.3.1. 什么是结构体? 71 4.3.2. 结构体声明 73 4.3.3. 结构体初始化 77 4.3.4. 嵌套结构体(Nested Structs) 81 4.3.5. 匿名字段 82 4.3.6. 导出结构体和字段 84 4.3.7. 结构体相等性(Structs Equality) 85 4.4. 指针类型 86 4.5. 函数 87 4.6. map 87 4.6.1. 什么是map 87 4.6.2. 声明、初始化和make 89 4.6.3. 给 map 添加元素 91 4.6.4. 获取 map 中的元素 91 4.6.5. 删除 map 中的元素 92 4.6.6. 获取 map 的长度 92 4.6.7. Map 的相等性 92 4.6.8. map的排序 92 4.7. 接口 93 4.7.1. 什么是接口? 93 4.7.2. 接口的声明与实现 96 4.7.3. 接口的实际用途 97 4.7.4. 接口的内部表示 99 4.7.5. 空接口 102 4.7.6. 类型断言 105 4.7.7. 类型选择(Type Switch) 109 4.7.8. 实现接口:指针接受者与值接受者 112 4.7.9. 实现多个接口 114 4.7.10. 接口的嵌套 116 4.7.11. 接口的零值 119 4.8. Channel 120 4.9. 类型转换 120 5. 函数 120 5.1. 函数的声明 121 5.2. 一个递归函数的例子( recursive functions) 121 5.3. 多返回值 121 5.4. 命名返回值 121 5.5. 可变函数参数 122 5.6. Defer 123 5.6.1. Defer语句介绍 123 5.6.2. Defer使用场景 128 5.7. 什么是头等(第一类)函数? 130 5.8. 匿名函数 130 5.9. 用户自定义的函数类型 132 5.10. 高阶函数(装饰器?) 133 5.10.1. 把函数作为参数,传递给其它函数 134 5.10.2. 在其它函数中返回函数 134 5.11. 闭包 135 5.12. 头等函数的实际用途 137 6. 微服务创建 140 6.1. 使用net/http创建简单的web server 140 6.2. 读写JSON 144 6.2.1. Marshal go结构到JSON 144 6.2.2. Unmarshalling JSON 到Go结构 146 7. 方法 146 7.1. 什么是方法? 146 7.2. 方法示例 146 7.3. 函数和方法区别 148 7.4. 指针接收器与值接收器 153 7.5. 那么什么时候使用指针接收器,什么时候使用值接收器? 155 7.6. 匿名字段的方法 156 7.7. 在方法中使用值接收器 与 在函数中使用值参数 157 7.8. 在方法中使用指针接收器 与 在函数中使用指针参数 159 7.9. 在非结构体上的方法 161 8. 并发入门 162 8.1. 并发是什么? 162 8.2. 并行是什么? 162 8.3. 从技术上看并发和并行 163 8.4. Go 对并发的支持 164 9. Go 协程 164 9.1. Go 协程是什么? 164 9.2. Go 协程相比于线程的优势 164 9.3. 如何启动一个 Go 协程? 165 9.4. 启动多个 Go 协程 167 10. 信道channel 169 10.1. 什么是信道? 169 10.2. 信道的声明 169 10.3. 通过信道进行发送和接收 169 10.4. 发送与接收默认是阻塞的 170 10.5. 信道的代码示例 170 10.6. 信道的另一个示例 173 10.7. 死锁 174 10.8. 单向信道 175 10.9. 关闭信道和使用 for range 遍历信道 176 11. 缓冲信道和工作池(Buffered Channels and Worker Pools) 179 11.1. 什么是缓冲信道? 179 11.2. 死锁 182 11.3. 长度 vs 容量 183 11.4. WaitGroup 184 11.5. 工作池的实现 186 12. Select 188 12.1. 什么是 select? 188 12.2. 示例 189 12.3. select 的应用 190 12.4. 默认情况 190 12.5. 死锁与默认情况 191 12.6. 随机选取 191 12.7. 这下我懂了:空 select 191 13. 文件读写 191 13.1. GoLang几种读文件方式的比较 197 14. 个人 197 14.1. ++,-- 198 14.2. 逗号 198 14.3. 未使用的变量 199 14.4. Effective go 199 14.4.1. 指针 vs. 值 199 14.5. 可寻址性-map和slice的区别 201 14.5.1. slice 201 14.5.2. map 202 14.6. golang库 203 14.6.1. unicode/utf8包 203 14.6.2. time包 205 14.6.3. Strings包 205 14.6.4. 输入输出 212 14.6.5. 正则处理 224 14.6.6. Golang内建函数 226

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值