走进 Go 语言基础语言
Go语言是一种开源的编程语言,于2009年由Google公司开发并推出。Go语言旨在提高程序员的生产力,同时具有高效、可靠和简洁等特点。目前,许多知名的公司和项目都在使用Go语言,如谷歌、Uber、Docker、Kubernetes等等。
什么是Go语言
Go语言是一种静态类型、编译型语言,它具有高效、可靠、简单、安全等特点。Go语言的语法简单,容易上手,而且可以在不同的操作系统上编译运行。
哪些公司在使用Go语言
许多知名的公司和项目都在使用Go语言,以下是一些例子:
- 谷歌:Go语言的创造者就是谷歌的三位工程师之一,目前谷歌内部有大量的Go语言项目。
- Uber:Uber的后端系统采用了大量的Go语言开发。
- Docker:Docker的核心组件都是用Go语言编写的。
- Kubernetes:Kubernetes是一个开源的容器编排引擎,也是用Go语言编写的。
- 等等
字节跳动为什么全面拥抱Go语言
字节跳动是一家国内知名的互联网公司,旗下有很多知名的应用程序,如今已经成为了全球最有价值的创业公司之一。字节跳动早在2017年就开始推广Go语言,目前已经成为了公司的主要编程语言之一。字节跳动之所以选择Go语言,主要原因有以下几点:
- 高效:Go语言具有高效的并发性能,可以支持高并发的应用程序。
- 简洁:Go语言的语法简单、易学、易用,可以帮助开发者提高生产效率。
- 安全:Go语言有内存安全、类型安全等特性,可以有效地防止代码漏洞和攻击。
入门
开发环境
要学习Go语言,首先需要搭建好开发环境。Go语言的官方网站提供了各种操作系统的安装包,可以到官方网站下载对应的安装包进行安装。同时,也可以使用一些第三方的集成开发环境,如Goland、VSCode等。
基础语法
Go语言的基础语法与其他编程语言类似,包括变量、常量、运算符、流程控制语句等等。以下是一些基础语法的示例:
变量
Go语言中的变量声明需要使用var关键字,如下所示:
var a int = 10
var b, c string = "hello", "world"
可以看出,Go语言中的变量声明需要显式地指定类型。同时,也可以使用短变量声明语法:
x := 10
y, z := "hello", "world"
在使用短变量声明语法时,Go语言会根据变量的值自动推断出变量类型。
常量
Go语言中的常量声明需要使用const关键字,如下所示:
const pi float32 = 3.14
const (
apple = "red"
banana = "yellow"
)
常量的值在程序运行期间是不可修改的。
运算符
Go语言中支持各种常见的运算符,包括算术运算符、比较运算符、逻辑运算符等等。以下是一些常用的运算符示例:
a, b := 10, 20
c := a + b
d := a > b
e := true && false
流程控制语句
Go语言中的流程控制语句包括if语句、for语句、switch语句等等。以下是一些常用的流程控制语句示例:
if a > b {
fmt.Println("a is greater than b")
} else {
fmt.Println("a is less than or equal to b")
}
for i := 0; i < 10; i++ {
fmt.Println(i)
}
switch x {
case 1:
fmt.Println("x is 1")
case 2:
fmt.Println("x is 2")
default:
fmt.Println("x is not 1 or 2")
}
实战
猜数字游戏
猜数字游戏是一个简单的控制台游戏,玩家需要猜测一个随机数,直到猜对为止。以下是一个使用Go语言编写的猜数字游戏示例:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
target := rand.Intn(100) + 1
fmt.Println("Welcome to the guess the number game!")
fmt.Println("I'm thinking of a number between 1 and 100. Can you guess what it is?")
var guess int
for i := 1; ; i++ {
fmt.Printf("Guess #%d: ", i)
fmt.Scan(&guess)
if guess == target {
fmt.Printf("Congratulations, you guessed it in %d tries!\n", i)
break
} else if guess < target {
fmt.Println("Too low. Try again.")
} else {
fmt.Println("Too high. Try again.")
}
}
}
命令行词典
命令行词典是一个基于控制台的小型词典程序,可以通过命令行输入单词查询其翻译。以下是一个使用Go语言编写的命令行词典示例:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
)
type Translation struct {
Translation []string `json:"translation"`
}
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: dict <word>")
return
}
word := strings.Join(os.Args[1:], " ")
resp, err := http.Get("http://fanyi.youdao.com/translate?&doctype=json&type=AUTO&i=" + url.QueryEscape(word))
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
var data struct {
ErrorCode int `json:"errorCode"`
Translate []*Translation `json:"translateResult"`
}
err = json.Unmarshal(body, &data)
if err != nil {
fmt.Println(err)
return
}
if data.ErrorCode != 0 {
fmt.Printf("Failed to translate: error code %d\n", data.ErrorCode)
return
}
fmt.Printf("%s: %s\n", word, data.Translate[0].Translation[0])
}
socks5代理
socks5代理是一种常见的代理服务器协议,可以实现TCP和UDP流量的转发,常用于加速访问、隐藏真实IP等。以下是一个使用Go语言编写的socks5代理示例:
package main
import (
"fmt"
"io"
"log"
"net"
)
func handleConn(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
log.Println(err)
return
}
if buf[0] != 0x05 {
log.Println("Invalid SOCKS version:", buf[0])
return
}
n, err = conn.Write([]byte{0x05, 0x00})
if err != nil {
log.Println(err)
return
}
n, err = conn.Read(buf)
if err != nil {
log.Println(err)
return
}
if n < 10 || buf[1] != 0x01 {
log.Println("Invalid SOCKS5 request:", buf[:n])
return
}
addrType := buf[3]
var dest string
switch addrType {
case 0x01:
dest = net.IPv4(buf[4], buf[5], buf[6], buf[7]).String()
case 0x03:
dest = string(buf[5 : n-2])
case 0x04:
dest = net.IP(buf[4:8]).String()
default:
log.Println("Unknown address type:", addrType)
return
}
port := fmt.Sprintf("%d", (int(buf[n-2]) << 8) | int(buf[n-1]))
targetAddr := net.JoinHostPort(dest, port)
log.Println("Connecting to", targetAddr)
target, err := net.Dial("tcp", targetAddr)
if err != nil {
log.Println(err)
return
}
defer target.Close()
_, err = conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0})
if err != nil {
log.Println(err)
return
}
go io.Copy(target, conn)
io.Copy(conn, target)
}
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:1080")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Println(err)
continue
}
go handleConn(conn)
}
}
该示例中,程序首先监听本地1080端口,等待客户端连接。一旦有客户端连接,就向客户端发送0x05 0x00表示支持socks5协议,并等待客户端发送请求。
客户端请求的格式为:[VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT],其中:
- VER:协议版本,这里应该是0x05;
- CMD:命令,0x01表示CONNECT;
- RSV:保留字段,0x00;
- ATYP:地址类型,0x01表示IPv4地址,0x03表示域名,0x04表示IPv6地址;
- DST.ADDR:目标地址;
- DST.PORT:目标端口。
程序首先检查协议版本,然后向客户端发送0x05 0x00表示支持无需认证的连接。然后解析请求,获取目标地址和端口,并建立连接。最后在新建协程中将客户端和目标服务器的连接转发即可。
总结
本篇学习笔记主要介绍了Go语言的基础语法和几个简单的实战项目,包括猜数字游戏、命令行词典和socks5代理。其中,猜数字游戏主要介绍了Go语言的基本语法、控制流和函数;命令行词典主要介绍了Go语言的网络编程和JSON解析;socks5代理则介绍了Go语言的并发编程和网络编程。
总的来说,Go语言具有简洁的语法、高效的编译速度和良好的并发性能,是一门非常适合编写网络应用和系统工具的语言。对于想要学习Go语言的读者来说,可以从语法基础开始学习,并结合实际项目来加深理解。