百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

Go语言零基础入门指南(下篇)(go语言入门书)

liuian 2025-05-09 20:02 17 浏览

1. 并发编程

goroutine基础

Go版本:

func say(s string) {
    for i := 0; i < 3; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world") // 启动goroutine
    say("hello")
}

对比Python线程:

import threading

def say(s):
    for i in range(3):
        time.sleep(0.1)
        print(s)

threading.Thread(target=say, args=("world",)).start()
say("hello")

对比JavaScript异步:

async function say(s) {
    for (let i = 0; i < 3; i++) {
        await new Promise(resolve => setTimeout(resolve, 100));
        console.log(s);
    }
}

say("world");
say("hello");

关键区别:

  1. goroutine比线程更轻量(初始仅2KB栈)
  2. Go运行时自动调度goroutine到OS线程
  3. 语法简单,只需go关键字

channel通信

Go版本:

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c <- sum // 发送结果到channel
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}
    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    x, y := <-c, <-c // 从channel接收
    fmt.Println(x, y, x+y)
}

对比Python多进程:

from multiprocessing import Pipe

def sum(s, conn):
    conn.send(sum(s))
    conn.close()

parent_conn, child_conn = Pipe()
p1 = Process(target=sum, args=(s[:len(s)//2], child_conn))
p2 = Process(target=sum, args=(s[len(s)//2:], child_conn))
p1.start(); p2.start()
print(parent_conn.recv(), parent_conn.recv())

关键区别:

  1. channel是Go内置的线程安全通信机制
  2. 可以带缓冲(make(chan int, 100))
  3. 支持关闭channel和range遍历

select多路复用

Go版本:

func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c <- x:
            x, y = y, x+y
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}

对比JavaScript Promise.race:

async function fibonacci(callback, quitSignal) {
    let x = 0, y = 1;
    while (true) {
        const result = await Promise.race([
            new Promise(res => callback(res, x)),
            quitSignal
        ]);
        if (result === 'quit') return;
        [x, y] = [y, x + y];
    }
}

关键区别:

  1. select可以同时监控多个channel
  2. 常用于超时控制:
   select {
   case res := <-c:
       fmt.Println(res)
   case <-time.After(1 * time.Second):
       fmt.Println("timeout")
   }

2. 文件操作与IO

文件读写

Go版本:

// 读取文件
data, err := os.ReadFile("test.txt")
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(data))

// 写入文件
err = os.WriteFile("output.txt", []byte("Hello"), 0644)
if err != nil {
    log.Fatal(err)
}

对比Python:

with open('test.txt') as f:
    data = f.read()

with open('output.txt', 'w') as f:
    f.write("Hello")

对比JavaScript:

const fs = require('fs');
fs.readFile('test.txt', (err, data) => {
    console.log(data.toString());
});

fs.writeFile('output.txt', 'Hello', err => {});

JSON处理

Go版本:

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

// 编码
p := Person{"Alice", 25}
jsonData, _ := json.Marshal(p)

// 解码
var p2 Person
json.Unmarshal(jsonData, &p2)

对比Python:

import json

data = json.dumps({"name": "Alice", "age": 25})
p = json.loads(data)

对比JavaScript:

const data = JSON.stringify({name: "Alice", age: 25});
const p = JSON.parse(data);

关键区别:

  1. Go需要定义结构体对应JSON结构
  2. 字段标签控制JSON属性名
  3. 编解码可能返回错误需要处理

3. 测试与性能

单元测试

Go版本:

// math.go
func Add(a, b int) int {
    return a + b
}

// math_test.go
func TestAdd(t *testing.T) {
    result := Add(2, 3)
    if result != 5 {
        t.Errorf("Expected 5, got %d", result)
    }
}

运行测试:

go test

对比Python unittest:

import unittest

def add(a, b):
    return a + b

class TestMath(unittest.TestCase):
    def test_add(self):
        self.assertEqual(add(2, 3), 5)

基准测试

Go版本:

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(1, 2)
    }
}

运行基准测试:

go test -bench=.

4. 项目实践

简单HTTP服务

Go版本:

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", helloHandler)
    http.ListenAndServe(":8080", nil)
}

对比Python Flask:

from flask import Flask
app = Flask(__name__)

@app.route('/<name>')
def hello(name):
    return f"Hello, {name}!"

app.run(port=8080)

对比JavaScript Express:

const express = require('express');
const app = express();

app.get('/:name', (req, res) => {
    res.send(`Hello, ${req.params.name}!`);
});

app.listen(8080);

项目结构建议

典型Go项目布局:

myapp/
├── cmd/
│   └── myapp/
│       └── main.go
├── internal/
│   ├── handler/
│   ├── service/
│   └── repository/
├── pkg/
│   └── utils/
├── go.mod
├── go.sum
└── README.md

进一步学习资源

  1. 官方文档:https://golang.org/doc/
  2. 标准库参考:https://pkg.go.dev/std
  3. 经典书籍:《Go程序设计语言》《Go语言实战》
  4. 开源项目:Docker, Kubernetes, Etcd等Go项目源码

下篇介绍了Go最强大的并发特性和实际项目开发中的关键技能。Go通过goroutine和channel提供了独特的并发编程模型,相比其他语言的线程/异步方案更加简单高效。建议通过实际项目练习来巩固这些概念,逐步掌握Go语言的精髓。

相关推荐

Optional是个好东西,如果用错了就太可惜了

原文出处:https://xie.infoq.cn/article/e3d1f0f4f095397c44812a5be我们都知道,在Java8新增了一个类-Optional,主要是用来解决程...

IDEA建议:不要在字段上使用@Autowire了!

在使用IDEA写Spring相关的项目的时候,在字段上使用@Autowired注解时,总是会有一个波浪线提示:Fieldinjectionisnotrecommended.纳尼?我天天用,咋...

Spring源码|Spring实例Bean的方法

Spring实例Bean的方法,在AbstractAutowireCapableBeanFactory中的protectedBeanWrappercreateBeanInstance(String...

Spring技巧:深入研究Java 14和SpringBoot

在本期文章中,我们将介绍Java14中的新特性及其在构建基于SpringBoot的应用程序中的应用。开始,我们需要使用Java的最新版本,也是最棒的版本,Java14,它现在还没有发布。预计将于2...

Java开发200+个学习知识路线-史上最全(框架篇)

1.Spring框架深入SpringIOC容器:BeanFactory与ApplicationContextBean生命周期:实例化、属性填充、初始化、销毁依赖注入方式:构造器注入、Setter注...

年末将至,Java 开发者必须了解的 15 个Java 顶级开源项目

专注于Java领域优质技术,欢迎关注作者:SnailClimbStar的数量统计于2019-12-29。1.JavaGuideGuide哥大三开始维护的,目前算是纯Java类型项目中Sta...

字节跨平台框架 Lynx 开源:一个 Web 开发者的原生体验

最近各大厂都在开源自己的跨平台框架,前脚腾讯刚宣布计划四月开源基于Kotlin的跨平台框架「Kuikly」,后脚字节跳动旧开源了他们的跨平台框架「Lynx」,如果说Kuikly是一个面向...

我要狠狠的反驳“公司禁止使用Lombok”的观点

经常在其它各个地方在说公司禁止使用Lombok,我一直不明白为什么不让用,今天看到一篇文章列举了一下“缺点”,这里我只想狠狠地反驳,看到列举的理由我竟无言以对。原文如下:下面,结合我自己使用Lomb...

SpringBoot Lombok使用详解:从入门到精通(注解最全)

一、Lombok概述与基础使用1.1Lombok是什么Lombok是一个Java库,它通过注解的方式自动生成Java代码(如getter、setter、toString等),从而减少样板代码的编写,...

Java 8之后的那些新特性(六):记录类 Record Class

Java是一门面向对象的语言,而对于面向对象的语言中,一个众所周知的概念就是,对象是包含属性与行为的。比如HR系统中都会有雇员的概念,那雇员会有姓名,ID身份,性别等,这些我们称之为属性;而雇员同时肯...

为什么大厂要求安卓开发者掌握Kotlin和Jetpack?优雅草卓伊凡

为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡一、Kotlin:Android开发的现代语言选择1.1Kotlin是什么?Kotlin是由...

Kotlin这5招太绝了!码农秒变优雅艺术家!

Kotlin因其简洁性、空安全性和与Java的无缝互操作性而备受喜爱。虽然许多开发者熟悉协程、扩展函数和数据类等特性,但还有一些鲜为人知的特性可以让你的代码从仅仅能用变得真正优雅且异常简洁。让我们来看...

自行部署一款免费高颜值的IT资产管理系统-咖啡壶chemex

在运维时,ICT资产太多怎么办,还是用excel表格来管理?效率太低,也不好多人使用。在几个IT资产管理系统中选择比较中,最终在Snipe-IT和chemex间选择了chemex咖啡壶。Snip...

PHP对接百度语音识别技术(php对接百度语音识别技术实验报告)

引言在目前的各种应用场景中,语音识别技术已经越来越常用,并且其应用场景正在不断扩大。百度提供的语音识别服务允许用户通过简单的接口调用,将语音内容转换为文本。本文将通过PHP语言集成百度的语音识别服务,...

知识付费系统功能全解析(知识付费项目怎么样)

开发知识付费系统需包含核心功能模块,确保内容变现、用户体验及运营管理需求。以下是完整功能架构:一、用户端功能注册登录:手机号/邮箱注册,第三方登录(微信、QQ)内容浏览:分类展示课程、文章、音频等付费...