最全Go基础学习笔记(一):基础语法、内建容器、面向对象(1),2024年最新这操作真香

img
img

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

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

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

		maxLength = i - start + 1
	}
	lastOccurred[ch] = i
}
return maxLength

}


##### 6)、字符和字符串处理


1)rune相当于go的char



s := "你好世界!"
fmt.Println(len(s))    // 15
for i, ch := range s { // ch is a rune
	fmt.Printf("(%d %X)", i, ch) // (0 4F60)(3 597D)(6 4E16)(9 754C)(12 FF01)
}
fmt.Println()

fmt.Println(utf8.RuneCountInString(s)) // 5

bytes := []byte(s)
for len(bytes) > 0 {
	ch, size := utf8.DecodeRune(bytes)
	bytes = bytes[size:]
	fmt.Printf("%c", ch)
} // 你好世界!
fmt.Println()

for i, ch := range []rune(s) {
	fmt.Printf("(%d %c)", i, ch)
} // (0 你)(1 好)(2 世)(3 界)(4 !)
fmt.Println()

* 使用range遍历pos rune对
* 使用`utf8.RuneCountInString`获得字符数量
* 使用len获得字节长度
* 使用[]byte获得字节


[最长不含重复字符的子字符串](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)支持中文



func lengthOfLongestSubstring(s string) int {
lastOccurred := make(map[rune]int)
start, maxLength := 0, 0
for i, ch := range []rune(s) {
lastI, ok := lastOccurred[ch]
if ok && lastI >= start {
start = lastOccurred[ch] + 1
}
if i-start+1 > maxLength {
maxLength = i - start + 1
}
lastOccurred[ch] = i
}
return maxLength
}


2)其他字符串操作


* Fields,Split,Join
* Contains,Index
* ToLower,ToUpper
* Trim,TrimRight,TrimLeft


#### 3、面向对象


##### 1)、结构体和方法


1)面向对象


* Go语言仅支持封装,不支持继承和多态
* Go语言没有class,只有struct


2)结构的创建



type treeNode struct {
value int
left, right *treeNode
}

func createNode(value int) *treeNode {
return &treeNode{value: value}
}

func main() {
root := treeNode{value: 3}
root.left = &treeNode{}
root.right = &treeNode{5, nil, nil}
root.right.left = new(treeNode)
root.left.right = createNode(2)
}


* 使用自定义工厂函数
* 注意返回了局部变量的地址


3)为结构定义方法



package main

import “fmt”

type treeNode struct {
value int
left, right *treeNode
}

func (node treeNode) print() {
fmt.Print(node.value, " ")
}

func (node treeNode) setValue(value int) {
node.value = value
}

func (node *treeNode) setValue2(value int) {
node.value = value
}

// 中序遍历
func (node *treeNode) traverse() {
if node == nil {
return
}
node.left.traverse()
node.print()
node.right.traverse()
}

func createNode(value int) *treeNode {
return &treeNode{value: value}
}

func main() {
root := treeNode{value: 3}
root.left = &treeNode{}
root.right = &treeNode{5, nil, nil}
root.right.left = new(treeNode)
root.left.right = createNode(2)
root.print() // 3
fmt.Println()

root.right.left.setValue(4)
root.right.left.print() // 0
root.right.left.setValue2(4)
root.right.left.print() // 4
fmt.Println()

root.traverse() // 0 2 3 4 5

}


* 显示定义和命名方法接收者
* 只有使用指针才可以改变结构内容
* nil指针也可以调用方法


4)值接收者 vs 指针接收者


* 要改变内容必须使用指针接收者
* 结构过大也考虑使用指针接收者
* 一致性:如有指针接收者,最好都是指针接收者
* 值接收者是Go语言特有
* 值/指针接收者均可接收值/指针


##### 2)、包和封装


1)封装


* 名字一般使用CamelCase
* 首字母大写:public
* 首字母小写:private


2)包


* 每个目录一个包
* main包包含可执行入口
* 为结构定义的方法必须放在同一个包内,可以是不同文件



go mod init tree



package node

import “fmt”

type TreeNode struct {
Value int
Left, Right *TreeNode
}

func (node TreeNode) Print() {
fmt.Print(node.Value, " ")
}

func (node TreeNode) SetValue(value int) {
node.Value = value
}

func (node *TreeNode) SetValue2(value int) {
node.Value = value
}

func CreateNode(value int) *TreeNode {
return &TreeNode{Value: value}
}



package node

// 中序遍历
func (node *TreeNode) Traverse() {
if node == nil {
return
}
node.Left.Traverse()
node.Print()
node.Right.Traverse()
}



package main

import (
“fmt”
“tree/node”
)

func main() {
root := node.TreeNode{Value: 3}
root.Left = &node.TreeNode{}
root.Right = &node.TreeNode{5, nil, nil}
root.Right.Left = new(node.TreeNode)
root.Left.Right = node.CreateNode(2)
root.Print() // 3
fmt.Println()

root.Right.Left.SetValue(4)
root.Right.Left.Print() // 0
root.Right.Left.SetValue2(4)
root.Right.Left.Print() // 4
fmt.Println()

root.Traverse() // 0 2 3 4 5

}


##### 3)、扩展已有类型


如何扩充系统类型或者别人的类型


* 定义别名
* 使用组合


1)使用组合



package main

import (
“fmt”
“tree/node”
)

type myTreeNode struct {
node *node.TreeNode
}

// 后序遍历
func (myNode *myTreeNode) postOrder() {
if myNode == nil || myNode.node == nil {
return
}
left := myTreeNode{myNode.node.Left}
left.postOrder()
right := myTreeNode{myNode.node.Right}
right.postOrder()
myNode.node.Print()
}

func main() {
root := node.TreeNode{Value: 3}
root.Left = &node.TreeNode{}
root.Right = &node.TreeNode{5, nil, nil}
root.Right.Left = new(node.TreeNode)
root.Left.Right = node.CreateNode(2)
root.Print() // 3
fmt.Println()

root.Right.Left.SetValue(4)
root.Right.Left.Print() // 0
root.Right.Left.SetValue2(4)
root.Right.Left.Print() // 4
fmt.Println()

root.Traverse() // 0 2 3 4 5
fmt.Println()

myRoot := myTreeNode{&root}
myRoot.postOrder() // 2 0 4 5 3

}


2)定义别名



go mod init queue



package queue

type Queue []int

func (q *Queue) Push(v int) {
*q = append(*q, v)
}

func (q *Queue) Pop() int {
head := (*q)[0]
*q = (*q)[1:]
return head
}

func (q *Queue) IsEmpty() bool {
return len(*q) == 0
}



package main

import (
“fmt”
“queue/queue”
)

func main() {
q := queue.Queue{1}
q.Push(2)
q.Push(3)
fmt.Println(q.Pop()) // 1
fmt.Println(q.Pop()) // 2
fmt.Println(q.IsEmpty()) // false
fmt.Println(q.Pop()) // 3
fmt.Println(q.IsEmpty()) // true
}


##### 4)、使用内嵌来扩展已有类型



package main

import (
“fmt”
“tree/node”
)

type myTreeNode struct {
*node.TreeNode // Embedding 内嵌
}

// 后序遍历
func (myNode *myTreeNode) postOrder() {
if myNode == nil || myNode.TreeNode == nil {
return
}
left := myTreeNode{myNode.Left}
left.postOrder()
right := myTreeNode{myNode.Right}
right.postOrder()
myNode.Print()
}

func (myNode *myTreeNode) Traverse() {
fmt.Println(“This method is shadowed.”)
}

func main() {
root := myTreeNode{&node.TreeNode{Value: 3}}
root.Left = &node.TreeNode{}
root.Right = &node.TreeNode{5, nil, nil}
root.Right.Left = new(node.TreeNode)
root.Left.Right = node.CreateNode(2)
root.Print() // 3
fmt.Println()

root.Right.Left.SetValue(4)
root.Right.Left.Print() // 0
root.Right.Left.SetValue2(4)
root.Right.Left.Print() // 4
fmt.Println()

root.TreeNode.Traverse() // 0 2 3 4 5
fmt.Println()

root.Traverse() // This method is shadowed.

root.postOrder() // 2 0 4 5 3

}


#### 4、Go语言的依赖管理


##### 1)、依赖管理


依赖管理的三个阶段:GOPATH,GOVENDOR,go mod


##### 2)、go mod的使用



go mod init gomodtest



go get -u go.uber.org/zap


![](https://img-blog.csdnimg.cn/d07267a939364f70bac6aa488d1c4b56.png#pic_center)
go.mod文件中指定了依赖库的版本,同时新增了一个go.sum的文件



package main

import “go.uber.org/zap”

func main() {
logger, _ := zap.NewProduction()
logger.Warn(“warning test”)
}


指定版本:



go get -u go.uber.org/zap@v1.11


go mod:


* 由go命令统一的管理,用户不必关心目录结构
* 初始化:go mod init
* 增加依赖:go get
* 更新依赖:go get [@v…],go mod tidy


#### 5、面向接口


##### 1)、接口的概念



package infra

import (
“io/ioutil”
“net/http”
)

type Retriever struct {
}

func (Retriever) Get(url string) string {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
bytes, _ := ioutil.ReadAll(resp.Body)
return string(bytes)
}



package testing

type Retriever struct {
}

func (Retriever) Get(url string) string {
return “fake content”
}



package main

import (
“fmt”
“learngo/downloader/infra”
“learngo/downloader/testing”
)

func getTestingRetriever() retriever {
return testing.Retriever{}
}

func getInfraRetriever() retriever {
return infra.Retriever{}
}

type retriever interface {
Get(url string) string
}

func main() {
url := “https://blog.csdn.net”
fmt.Println(getInfraRetriever().Get(url))
fmt.Println(getTestingRetriever().Get(url))
}


##### 2)、duck typing的概念


* 像鸭子走路,像鸭子叫(长得像鸭子),那么就是鸭子
* 描述事物的外部行为而非内部结构
* 严格说Go语言属于结构化类型系统,类似duck typing


##### 3)、接口的定义和实现


1)接口的定义


![](https://img-blog.csdnimg.cn/0fde35aaf7f04fd3a901086bf91984d7.png#pic_center)
* 接口由使用者定义


2)接口的实现


* 接口的实现是隐式的
* 只要实现接口里的方法



package mock

type Retriever struct {
Contents string
}

func (r Retriever) Get(url string) string {
return r.Contents
}



package real

import (
“net/http”
“net/http/httputil”
“time”
)

type Retriever struct {
UserAgent string
TimeOut time.Duration
}

func (r Retriever) Get(url string) string {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
result, err := httputil.DumpResponse(resp, true)
defer resp.Body.Close()
if err != nil {
panic(err)
}
return string(result)
}



package main

import (
“fmt”
“learngo/retriever/mock”
“learngo/retriever/real”
)

type Retriever interface {
Get(url string) string
}

func download(r Retriever) string {
return r.Get(“https://blog.csdn.net”)
}

func main() {
var r Retriever
r = real.Retriever{}
fmt.Println(download®)

r = mock.Retriever{"this is a fake blog.csdn.net"}
fmt.Println(download(r))

}


##### 4)、接口的值类型



package mock

type Retriever struct {
Contents string
}

func (r Retriever) Get(url string) string {
return r.Contents
}



package real

import (
“net/http”
“net/http/httputil”
“time”
)

type Retriever struct {
UserAgent string
TimeOut time.Duration
}

func (r *Retriever) Get(url string) string {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
result, err := httputil.DumpResponse(resp, true)
defer resp.Body.Close()
if err != nil {
panic(err)
}
return string(result)
}



package main

import (
“fmt”
“learngo/retriever/mock”
“learngo/retriever/real”
“time”
)

type Retriever interface {
Get(url string) string
}

func download(r Retriever) string {
return r.Get(“https://blog.csdn.net”)
}

func inspect(r Retriever) {
switch v := r.(type) {
case mock.Retriever:
fmt.Println(“Contents:”, v.Contents)
case *real.Retriever:
fmt.Println(“UserAgent:”, v.UserAgent)
}
}

func main() {
var r Retriever
r = mock.Retriever{Contents: “this is a fake blog.csdn.net”}
fmt.Printf(“%T %v\n”, r, r) // mock.Retriever {this is a fake blog.csdn.net}
inspect® // Contents: this is a fake blog.csdn.net

r = &real.Retriever{UserAgent: "Mozilla/5.0", TimeOut: time.Minute}
fmt.Printf("%T %v\n", r, r) // \*real.Retriever &{Mozilla/5.0 1m0s}
inspect(r)                  // UserAgent: Mozilla/5.0

// Type assertion
realRetriever := r.(\*real.Retriever)
fmt.Println(realRetriever.TimeOut)

if mockRetriever, ok := r.(mock.Retriever); ok {
	fmt.Println(mockRetriever.Contents)
} else {
	fmt.Println("not a mock retriever")
}

}


1)接口变量里面有什么


![](https://img-blog.csdnimg.cn/fc5d0d46da9d4a5fb97866af3a2e00a1.png#pic_center)
![](https://img-blog.csdnimg.cn/7956a30a25ac4cdb83ecbdab011108bb.png#pic_center)
* 接口变量自带指针
* 接口变量同样采用值传递,几乎不需要使用接口的指针
* 指针接收者实现只能以指针方式使用;值接收者都可以


2)查看接口变量


* 表示任何类型:interface{}
* Type Assertion
* Type Switch



package queue

type Queue []interface{}

func (q *Queue) Push(v interface{}) {
*q = append(*q, v)
}

func (q *Queue) Pop() interface{} {
head := (*q)[0]
*q = (*q)[1:]
return head
}

func (q *Queue) IsEmpty() bool {
return len(*q) == 0
}



package main

import (
“fmt”
“learngo/queue/queue”
)

func main() {
q := queue.Queue{1}
q.Push(2)
q.Push(3)
fmt.Println(q.Pop()) // 1
fmt.Println(q.Pop()) // 2
fmt.Println(q.IsEmpty()) // false
fmt.Println(q.Pop()) // 3
fmt.Println(q.IsEmpty()) // true
q.Push(“abc”)
fmt.Println(q.Pop()) // abc
}


##### 5)、接口的组合



package mock

type Retriever struct {
Contents string
}

func (r *Retriever) Get(url string) string {
return r.Contents
}

func (r *Retriever) Post(url string, form map[string]string) string {
r.Contents = form[“contents”]
return “ok”
}



package main

import (
“fmt”
“learngo/retriever/mock”
“learngo/retriever/real”
“time”
)

const url = “https://blog.csdn.net”

type Retriever interface {
Get(url string) string
}

type Poster interface {
Post(url string, form map[string]string) string
}

func download(r Retriever) string {
return r.Get(url)
}

func post(poster Poster) {
poster.Post(url,
map[string]string{
“name”: “xiaoming”,
})
}

type RetrieverPoster interface {
Retriever
Poster
}

func session(s RetrieverPoster) string {
s.Post(url, map[string]string{
“contents”: “another fake blog.csdn.net”,
})
return s.Get(url)
}

func inspect(r Retriever) {
switch v := r.(type) {
case *mock.Retriever:
fmt.Println(“Contents:”, v.Contents)
case *real.Retriever:
fmt.Println(“UserAgent:”, v.UserAgent)
}
}

func main() {
var r Retriever
retriever := mock.Retriever{Contents: “this is a fake blog.csdn.net”}
r = &retriever
fmt.Printf(“%T %v\n”, r, r) // *mock.Retriever &{this is a fake blog.csdn.net}
inspect® // Contents: this is a fake blog.csdn.net

r = &real.Retriever{UserAgent: "Mozilla/5.0", TimeOut: time.Minute}
fmt.Printf("%T %v\n", r, r) // \*real.Retriever &{Mozilla/5.0 1m0s}
inspect(r)                  // UserAgent: Mozilla/5.0

// Type assertion
realRetriever := r.(\*real.Retriever)
fmt.Println(realRetriever.TimeOut)

if mockRetriever, ok := r.(\*mock.Retriever); ok {
	fmt.Println(mockRetriever.Contents)
} else {
	fmt.Println("not a mock retriever")
}

fmt.Println(session(&retriever)) // another fake blog.csdn.net

}


##### 6)、常用系统接口


* Stringer
* Reader/Writer


#### 6、函数式编程


##### 1)、函数式编程


1)函数式编程 vs 函数指针


* 函数是一等公民:参数、变量、返回值都可以是函数
* 高阶函数
* 函数 -> 闭包


2)正统函数式编程


* 不可变性:不能有状态,只有常量和函数
* 函数只能有一个参数


3)闭包


![](https://img-blog.csdnimg.cn/26256603d9224bdab8f5fb10eb7fbd9f.png#pic_center)

func adder() func(int) int {
sum := 0
return func(v int) int {
sum += v
return sum
}
}

func main() {
a := adder()
for i := 0; i < 10; i++ {
fmt.Printf(“0 + 1 + … + %d = %d\n”, i, a(i))
}
}


##### 2)、函数式编程示例


1)斐波那契数列



func fibonacci() func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
return a
}
}

func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}


2)为函数实现接口



func fibonacci() intGen {
a, b := 0, 1
return func() int {
a, b = b, a+b
return a
}
}

type intGen func() int

func (g intGen) Read(p []byte) (n int, err error) {
next := g()
if next > 1000 {
return 0, io.EOF
}
s := fmt.Sprintf(“%d\n”, next)
return strings.NewReader(s).Read§
}

func printFileContents(reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}

func main() {
f := fibonacci()
printFileContents(f)
}


3)使用函数遍历二叉树



package node

import “fmt”

type TreeNode struct {
Value int
Left, Right *TreeNode
}

func (node TreeNode) Print() {
fmt.Print(node.Value, " ")
}

func CreateNode(value int) *TreeNode {
return &TreeNode{Value: value}
}



package node

import “fmt”

func (node *TreeNode) Traverse() {
node.TraverseFunc(func(node *TreeNode) {
node.Print()
})
fmt.Println()
}

// 中序遍历
func (node *TreeNode) TraverseFunc(f func(*TreeNode)) {
if node == nil {
return
}
node.Left.TraverseFunc(f)
f(node)
node.Right.TraverseFunc(f)
}



package main

import (
“fmt”
“learngo/tree/node”
)

func main() {
root := node.CreateNode(3)
root.Left = node.CreateNode(0)
root.Right = node.CreateNode(5)
root.Right.Left = node.CreateNode(4)
root.Left.Right = node.CreateNode(2)
root.Traverse() // 0 2 3 4 5
nodeCount := 0
root.TraverseFunc(func(node *node.TreeNode) {
nodeCount++
})

img
img
img

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

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

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

nc CreateNode(value int) *TreeNode {
return &TreeNode{Value: value}
}



package node

import “fmt”

func (node *TreeNode) Traverse() {
node.TraverseFunc(func(node *TreeNode) {
node.Print()
})
fmt.Println()
}

// 中序遍历
func (node *TreeNode) TraverseFunc(f func(*TreeNode)) {
if node == nil {
return
}
node.Left.TraverseFunc(f)
f(node)
node.Right.TraverseFunc(f)
}



package main

import (
“fmt”
“learngo/tree/node”
)

func main() {
root := node.CreateNode(3)
root.Left = node.CreateNode(0)
root.Right = node.CreateNode(5)
root.Right.Left = node.CreateNode(4)
root.Left.Right = node.CreateNode(2)
root.Traverse() // 0 2 3 4 5
nodeCount := 0
root.TraverseFunc(func(node *node.TreeNode) {
nodeCount++
})

[外链图片转存中…(img-e4TmIaUc-1715467906410)]
[外链图片转存中…(img-OP07Nq8V-1715467906410)]
[外链图片转存中…(img-gX5ncAe5-1715467906410)]

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

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

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

  • 15
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值