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

一举两得:Go和Rust同步学习指南_go与rust

zhezhongyun 2025-09-04 22:08 26 浏览

变量与常量

变量声明

Go

// 显式类型声明
var x int = 10

// 类型推断
var y = 20
z := 30  // 短变量声明,只能在函数内使用

// 批量声明
var (
    a int
    b string = "hello"
    c = 3.14
)

// 默认值
var zeroInt int      // 0
var zeroStr string   // ""
var zeroBool bool    // false

Rust

// 不可变变量(默认)
let x: i32 = 10;

// 类型推断
let y = 20;

// 可变变量
let mut z = 30;
z = 40;  // 只有mut变量可以修改

// 变量遮蔽(shadowing)
let a = 5;
let a = a + 1;  // 允许同名变量,创建新绑定

// 常量(必须显式类型)
const PI: f64 = 3.14159;

// 默认不可变是Rust的重要安全特性

基本数据类型

整数类型

Go

var i8 int8 = -128
var u8 uint8 = 255
var i16 int16 = -32768
var u16 uint16 = 65535
var i32 int32 = -2147483648
var u32 uint32 = 4294967295
var i64 int64 = -9223372036854775808
var u64 uint64 = 18446744073709551615
var i int // 平台相关,32或64位
var u uint // 平台相关
var r rune = '中' // int32的别名
var b byte = 255 // uint8的别名

Rust

let i8: i8 = -128;
let u8: u8 = 255;
let i16: i16 = -32768;
let u16: u16 = 65535;
let i32: i32 = -2147483648;
let u32: u32 = 4294967295;
let i64: i64 = -9223372036854775808;
let u64: u64 = 18446744073709551615;
let isize: isize = -1; // 平台相关
let usize: usize = 1;  // 平台相关
let char = '中'; // Unicode标量值,4字节

浮点类型

Go

var f32 float32 = 3.14
var f64 float64 = 3.141592653589793

Rust

let f32: f32 = 3.14;
let f64: f64 = 3.141592653589793;

布尔类型

Go

var b1 bool = true
var b2 = false

Rust

let b1: bool = true;
let b2 = false;

字符串类型

Go

// 字符串是不可变的字节序列
var s1 string = "hello"
s2 := "world"

// 原始字符串(不转义)
s3 := `line 1
line 2\n`  // \n不会被转义

// 字符串拼接
s4 := s1 + " " + s2

Rust

// 字符串切片(不可变引用)
let s1: &str = "hello";

// String类型(可增长、可修改)
let mut s2 = String::from("world");

// 原始字符串
let s3 = r"line 1\nline 2";  // \n不会被转义
let s4 = r#"字符串可以包含"引号""#;

// 字符串拼接
let s5 = format!("{} {}", s1, s2);  // 创建新String
s2.push_str("!");  // 修改现有String

控制结构

条件语句

Go

// 基本if
if x > 0 {
    fmt.Println("positive")
}

// if with short statement
if y := compute(); y < 0 {
    fmt.Println("negative")
} else if y == 0 {
    fmt.Println("zero")
} else {
    fmt.Println("positive")
}

// switch
switch os := runtime.GOOS; os {
case "darwin":
    fmt.Println("macOS")
case "linux":
    fmt.Println("Linux")
default:
    fmt.Printf("%s\n", os)
}

// 无条件的switch(相当于if-else链)
switch {
case x < 0:
    fmt.Println("negative")
case x == 0:
    fmt.Println("zero")
default:
    fmt.Println("positive")
}

Rust

// 基本if
if x > 0 {
    println!("positive");
}

// if-else if-else
let y = compute();
if y < 0 {
    println!("negative");
} else if y == 0 {
    println!("zero");
} else {
    println!("positive");
}

// if是表达式
let result = if y > 0 { "positive" } else { "non-positive" };

// match(比switch更强大)
match x.cmp(&0) {
    std::cmp::Ordering::Less => println!("negative"),
    std::cmp::Ordering::Equal => println!("zero"),
    std::cmp::Ordering::Greater => println!("positive"),
}

// match是表达式
let number = match x {
    1 => "one",
    2 => "two",
    3..=9 => "three to nine",  // 范围匹配
    _ => "other",  // 默认情况
};

循环

Go

// 传统for循环
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

// while循环(用for实现)
j := 0
for j < 10 {
    fmt.Println(j)
    j++
}

// 无限循环
for {
    if condition {
        break
    }
}

// range循环
nums := []int{1, 2, 3}
for i, num := range nums {
    fmt.Printf("index: %d, value: %d\n", i, num)
}

// 带标签的break
OuterLoop:
for i := 0; i < 10; i++ {
    for j := 0; j < 10; j++ {
        if i*j > 50 {
            break OuterLoop
        }
    }
}

Rust

// for循环(迭代器)
for i in 0..10 {  // 0..10是范围,不包括10
    println!("{}", i);
}

// while循环
let mut j = 0;
while j < 10 {
    println!("{}", j);
    j += 1;
}

// 无限循环(可返回值)
let result = loop {
    if condition {
        break 42;  // 返回42
    }
};

// 迭代集合
let nums = vec![1, 2, 3];
for (i, &num) in nums.iter().enumerate() {
    println!("index: {}, value: {}", i, num);
}

// 带标签的break
'outer: for i in 0..10 {
    for j in 0..10 {
        if i * j > 50 {
            break 'outer;
        }
    }
}

函数

基本函数

Go

// 基本函数
func add(a int, b int) int {
    return a + b
}

// 参数类型简写
func sub(a, b int) int {
    return a - b
}

// 多返回值
func swap(a, b string) (string, string) {
    return b, a
}

// 命名返回值
func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return  // 裸返回
}

// 可变参数
func sum(nums ...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

Rust

// 基本函数
fn add(a: i32, b: i32) -> i32 {
    a + b  // 没有分号,这是表达式
}

// 多返回值(使用元组)
fn swap(a: String, b: String) -> (String, String) {
    (b, a)
}

// 表达式与语句
fn five() -> i32 {
    5  // 表达式返回
}

fn plus_one(x: i32) -> i32 {
    x + 1  // 表达式返回
    // x + 1;  // 加上分号变成语句,会报错
}

// 可变参数(使用切片)
fn sum(nums: &[i32]) -> i32 {
    nums.iter().sum()
}

// 方法(关联函数)
impl Point {
    fn distance(&self, other: &Point) -> f64 {
        // 方法实现
    }
}

闭包(匿名函数)

Go

// 基本闭包
add := func(a, b int) int {
    return a + b
}
result := add(1, 2)

// 闭包捕获环境变量
x := 10
closure := func() int {
    return x * 2  // 捕获x
}
fmt.Println(closure())  // 20

Rust

// 基本闭包
let add = |a: i32, b: i32| -> i32 { a + b };
let result = add(1, 2);

// 类型推断
let add = |a, b| a + b;  // 编译器能推断类型

// 捕获环境变量
let x = 10;
let closure = || x * 2;  // 不可变借用x
println!("{}", closure());  // 20

// 移动语义(强制获取所有权)
let s = String::from("hello");
let closure = move || println!("{}", s);  // s的所有权被移动
closure();
// println!("{}", s);  // 错误!s已被移动

复合数据类型

数组

Go

// 数组(固定长度)
var a [3]int = [3]int{1, 2, 3}
b := [...]int{1, 2, 3}  // 编译器推断长度

// 访问元素
first := a[0]

// 修改元素
a[1] = 20

// 遍历
for i, v := range a {
    fmt.Printf("index: %d, value: %d\n", i, v)
}

// 多维数组
var matrix [2][3]int = [2][3]int{
    {1, 2, 3},
    {4, 5, 6},
}

Rust

// 数组(固定长度)
let a: [i32; 3] = [1, 2, 3];
let b = [1, 2, 3];  // 类型推断

// 访问元素
let first = a[0];

// 修改元素(需要mut)
let mut c = [1, 2, 3];
c[1] = 20;

// 遍历
for (i, &v) in a.iter().enumerate() {
    println!("index: {}, value: {}", i, v);
}

// 多维数组
let matrix: [[i32; 3]; 2] = [
    [1, 2, 3],
    [4, 5, 6],
];

切片/向量

Go

// 切片(动态大小视图)
s := []int{1, 2, 3}  // 切片字面量
var s2 []int         // 零值是nil

// 从数组创建切片
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4]  // [2, 3, 4]

// 修改切片会影响底层数组
slice[0] = 20
fmt.Println(arr)  // [1, 20, 3, 4, 5]

// 常用操作
s = append(s, 4)       // 追加
length := len(s)       // 长度
capacity := cap(s)     // 容量
sub := s[1:3]         // 子切片
copy(sub, []int{9,8}) // 复制

// make创建切片
s3 := make([]int, 5)     // 长度5,容量5
s4 := make([]int, 0, 10) // 长度0,容量10

Rust

// 切片(不可变视图)
let arr = [1, 2, 3, 4, 5];
let slice: &[i32] = &arr[1..4];  // [2, 3, 4]

// 向量(Vec,可增长数组)
let mut vec = vec![1, 2, 3];
vec.push(4);            // 追加
let first = vec[0];     // 访问
vec[1] = 20;           // 修改

// 常用操作
let len = vec.len();    // 长度
let cap = vec.capacity(); // 容量
let sub = &vec[1..3];   // 子切片
vec.extend([5,6]);      // 扩展
vec.insert(1, 10);      // 插入
vec.remove(2);          // 移除

// 迭代
for v in &vec {
    println!("{}", v);
}

结构体

Go

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

// 创建实例
p1 := Person{"Alice", 30}
p2 := Person{Name: "Bob", Age: 25}

// 匿名结构体
p3 := struct {
    Name string
    Age  int
}{
    Name: "Charlie",
    Age: 35,
}

// 方法
func (p Person) Greet() string {
    return fmt.Sprintf("Hello, my name is %s", p.Name)
}

// 指针接收者方法(可修改结构体)
func (p *Person) Birthday() {
    p.Age++
}

// 嵌套结构体
type Employee struct {
    Person
    JobTitle string
}

Rust

// 定义结构体
struct Person {
    name: String,
    age: i32,
}

// 创建实例
let p1 = Person {
    name: String::from("Alice"),
    age: 30,
};

// 更新语法
let p2 = Person {
    name: String::from("Bob"),
    ..p1  // 使用p1的其他字段
};

// 元组结构体
struct Color(i32, i32, i32);
let black = Color(0, 0, 0);

// 方法
impl Person {
    fn greet(&self) -> String {
        format!("Hello, my name is {}", self.name)
    }
    
    fn birthday(&mut self) {
        self.age += 1;
    }
    
    // 关联函数(类似静态方法)
    fn new(name: String, age: i32) -> Self {
        Person { name, age }
    }
}

// 嵌套结构体
struct Employee {
    person: Person,
    job_title: String,
}

枚举

Go

// Go没有原生枚举,通常用常量模拟
type Direction int

const (
    North Direction = iota
    East
    South
    West
)

func (d Direction) String() string {
    return [...]string{"North", "East", "South", "West"}[d]
}

// 带值的枚举(使用结构体和接口)
type Shape interface {
    area() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) area() float64 {
    return math.Pi * c.Radius * c.Radius
}

type Rectangle struct {
    Width, Height float64
}

func (r Rectangle) area() float64 {
    return r.Width * r.Height
}

Rust

// 基本枚举
enum Direction {
    North,
    East,
    South,
    West,
}

// 带数据的枚举
enum Shape {
    Circle(f64),          // 半径
    Rectangle(f64, f64),  // 宽和高
    Square(f64),          // 边长
}

// 方法
impl Shape {
    fn area(&self) -> f64 {
        match self {
            Shape::Circle(r) => std::f64::consts::PI * r * r,
            Shape::Rectangle(w, h) => w * h,
            Shape::Square(s) => s * s,
        }
    }
}

// Option枚举(标准库)
enum Option<T> {
    Some(T),
    None,
}

// Result枚举(标准库)
enum Result<T, E> {
    Ok(T),
    Err(E),
}

错误处理

Go

// 多返回值错误处理
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return a / b, nil
}

result, err := divide(10, 0)
if err != nil {
    log.Fatal(err)
}

// 自定义错误类型
type MyError struct {
    Msg string
    Code int
}

func (e *MyError) Error() string {
    return fmt.Sprintf("code %d: %s", e.Code, e.Msg)
}

func process() error {
    return &MyError{"something went wrong", 500}
}

// panic和recover
func risky() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered:", r)
        }
    }()
    panic("something bad happened")
}

Rust

// Result类型处理
fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err(String::from("division by zero"))
    } else {
        Ok(a / b)
    }
}

match divide(10.0, 0.0) {
    Ok(result) => println!("Result: {}", result),
    Err(e) => println!("Error: {}", e),
}

// 更简洁的写法(使用?运算符)
fn calculate() -> Result<f64, String> {
    let x = divide(10.0, 2.0)?;  // 如果Err会提前返回
    let y = divide(x, 3.0)?;
    Ok(y)
}

// 自定义错误类型(更推荐的方式)
#[derive(Debug)]
enum MathError {
    DivisionByZero,
    NegativeLogarithm,
}

impl std::fmt::Display for MathError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            MathError::DivisionByZero => write!(f, "division by zero"),
            MathError::NegativeLogarithm => write!(f, "logarithm of negative number"),
        }
    }
}

fn better_divide(a: f64, b: f64) -> Result<f64, MathError> {
    if b == 0.0 {
        Err(MathError::DivisionByZero)
    } else {
        Ok(a / b)
    }
}

// panic和unwrap
let x: i32 = "123".parse().unwrap();  // 成功时返回值,失败时panic
let y: i32 = "abc".parse().expect("Failed to parse number");  // 自定义panic消息

并发编程

Go

// goroutine
go func() {
    fmt.Println("Running in goroutine")
}()

// WaitGroup等待多个goroutine完成
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(n int) {
        defer wg.Done()
        fmt.Println(n)
    }(i)
}
wg.Wait()

// channel通信
ch := make(chan int)
go func() {
    ch <- 42  // 发送
}()
value := <-ch  // 接收

// 缓冲channel
bufCh := make(chan int, 2)
bufCh <- 1
bufCh <- 2

// select多路复用
select {
case v := <-ch1:
    fmt.Println(v)
case v := <-ch2:
    fmt.Println(v)
case <-time.After(time.Second):
    fmt.Println("timeout")
default:
    fmt.Println("no activity")
}

// sync.Mutex互斥锁
var mu sync.Mutex
var counter int
for i := 0; i < 10; i++ {
    go func() {
        mu.Lock()
        defer mu.Unlock()
        counter++
    }()
}

Rust

// 线程
let handle = std::thread::spawn(|| {
    println!("Running in thread");
});
handle.join().unwrap();  // 等待线程结束

// 通道通信
let (tx, rx) = std::sync::mpsc::channel();
std::thread::spawn(move || {
    tx.send(42).unwrap();  // 发送
});
let value = rx.recv().unwrap();  // 接收

// 共享状态并发(Arc + Mutex)
use std::sync::{Arc, Mutex};
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];

for _ in 0..10 {
    let counter = Arc::clone(&counter);
    let handle = std::thread::spawn(move || {
        let mut num = counter.lock().unwrap();
        *num += 1;
    });
    handles.push(handle);
}

for handle in handles {
    handle.join().unwrap();
}

// async/await(异步编程)
async fn fetch_data() -> Result<String, reqwest::Error> {
    reqwest::get("https://example.com")
        .await?
        .text()
        .await
}

#[tokio::main]
async fn main() {
    match fetch_data().await {
        Ok(data) => println!("Got data: {}", data),
        Err(e) => println!("Error: {}", e),
    }
}

相关推荐

Python入门学习记录之一:变量_python怎么用变量

写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...

python变量命名规则——来自小白的总结

python是一个动态编译类编程语言,所以程序在运行前不需要如C语言的先行编译动作,因此也只有在程序运行过程中才能发现程序的问题。基于此,python的变量就有一定的命名规范。python作为当前热门...

Python入门学习教程:第 2 章 变量与数据类型

2.1什么是变量?在编程中,变量就像一个存放数据的容器,它可以存储各种信息,并且这些信息可以被读取和修改。想象一下,变量就如同我们生活中的盒子,你可以把东西放进去,也可以随时拿出来看看,甚至可以换成...

绘制学术论文中的“三线表”具体指导

在科研过程中,大家用到最多的可能就是“三线表”。“三线表”,一般主要由三条横线构成,当然在变量名栏里也可以拆分单元格,出现更多的线。更重要的是,“三线表”也是一种数据记录规范,以“三线表”形式记录的数...

Python基础语法知识--变量和数据类型

学习Python中的变量和数据类型至关重要,因为它们构成了Python编程的基石。以下是帮助您了解Python中的变量和数据类型的分步指南:1.变量:变量在Python中用于存储数据值。它们充...

一文搞懂 Python 中的所有标点符号

反引号`无任何作用。传说Python3中它被移除是因为和单引号字符'太相似。波浪号~(按位取反符号)~被称为取反或补码运算符。它放在我们想要取反的对象前面。如果放在一个整数n...

Python变量类型和运算符_python中变量的含义

别再被小名词坑哭了:Python新手常犯的那些隐蔽错误,我用同事的真实bug拆给你看我记得有一次和同事张姐一起追查一个看似随机崩溃的脚本,最后发现罪魁祸首竟然是她把变量命名成了list。说实话...

从零开始:深入剖析 Spring Boot3 中配置文件的加载顺序

在当今的互联网软件开发领域,SpringBoot无疑是最为热门和广泛应用的框架之一。它以其强大的功能、便捷的开发体验,极大地提升了开发效率,成为众多开发者构建Web应用程序的首选。而在Spr...

Python中下划线 ‘_’ 的用法,你知道几种

Python中下划线()是一个有特殊含义和用途的符号,它可以用来表示以下几种情况:1在解释器中,下划线(_)表示上一个表达式的值,可以用来进行快速计算或测试。例如:>>>2+...

解锁Shell编程:变量_shell $变量

引言:开启Shell编程大门Shell作为用户与Linux内核之间的桥梁,为我们提供了强大的命令行交互方式。它不仅能执行简单的文件操作、进程管理,还能通过编写脚本实现复杂的自动化任务。无论是...

一文学会Python的变量命名规则!_python的变量命名有哪些要求

目录1.变量的命名原则3.内置函数尽量不要做变量4.删除变量和垃圾回收机制5.结语1.变量的命名原则①由英文字母、_(下划线)、或中文开头②变量名称只能由英文字母、数字、下画线或中文字所组成。③英文字...

更可靠的Rust-语法篇-区分语句/表达式,略览if/loop/while/for

src/main.rs://函数定义fnadd(a:i32,b:i32)->i32{a+b//末尾表达式}fnmain(){leta:i3...

C++第五课:变量的命名规则_c++中变量的命名规则

变量的命名不是想怎么起就怎么起的,而是有一套固定的规则的。具体规则:1.名字要合法:变量名必须是由字母、数字或下划线组成。例如:a,a1,a_1。2.开头不能是数字。例如:可以a1,但不能起1a。3....

Rust编程-核心篇-不安全编程_rust安全性

Unsafe的必要性Rust的所有权系统和类型系统为我们提供了强大的安全保障,但在某些情况下,我们需要突破这些限制来:与C代码交互实现底层系统编程优化性能关键代码实现某些编译器无法验证的安全操作Rus...

探秘 Python 内存管理:背后的神奇机制

在编程的世界里,内存管理就如同幕后的精密操控者,确保程序的高效运行。Python作为一种广泛使用的编程语言,其内存管理机制既巧妙又复杂,为开发者们提供了便利的同时,也展现了强大的底层控制能力。一、P...