Option类型:C++(std::optional)、Rust(Option)、Go(gob.OptionalValue)

当我们在实现一个函数 fn() point, 该函数会有返回的point指针有可能是null,那么函数的调用者必须显示的进行判断(避免出现null point引发的程序崩溃)。Rust作为强调系统安全的语言,自然是从语言层面上给予了开发者莫大的帮助(规范),c++ 17也引入了std::optional类型,但如果能再提供rust 的match 更好了,以下说明Option类型带来的编程改善

C++中std::optional的用法

(1) 定义 optional 对象
可以通过两种方式来定义 optional 对象。一种是直接把要封装的值传给 std::optional 的构造函数,另一种是使用 std::make_optional 工厂函数:
int value = 4;
std::optional<int> opt1 = value; // 通过构造函数
std::optional<int> opt2 = std::make_optional(value); // 使用 make_optional 工厂函数
(2) 判断是否有返回值
可以使用 bool has_value() 函数来判断 optional 对象是否含有值:
// 判断 opt1 是否含有值
if (opt1.has_value()) {
    
    
    std::cout << "opt1 has value\n";
}
(3) 获取返回值
如果 optional 对象中含有值,可以通过 value() 或者 * 来获取其中的值:
// opt1 中保存的值加 1
opt1.value() += 1;
// 也可以用 * 来获取保存的值
*opt1 += 1;
(4) optional 对象与普通变量/指针的比较
可以使用 == 将 optional 对象与 nullptr 进行比较:
// 等价于 opt1.has_value()
if (opt1 == nullptr) {
    
    
    std::cout << "opt1 is nullptr\n";
} else {
    
    
    std::cout << "opt1 has value\n";
}
也可以将 optional 对象和普通变量/指针进行比较:
// 等价于 opt1.has_value() && opt1.value() == 5
if (opt1 == 5) {
    
    
    std::cout << "opt1 == 5\n";
}

Rust中Option的用法

// Option type
let x: Option<i32> = Some(5);
match x {
    
    
    Some(i) => println!("x is {:?}", i),
    None => println!("x is none")
}

把Some构造函数看成类型转换函数,其可以将任何类型T,转成Option,而match时Some(i),可以解出i(option具有值)的具体值。
我们有可以使用unwrap来解出Option中的值,但需要特别注意的时,如果Option为None,那么会发生panic错误,所以是当调用者确认返回值的Option必然有值时才会使用unwrap()

Go中encoding/gob 库的使用(gob.OptionalValue)

gob.OptionalValue就是用来表示可选的这个值,它会维护一个bool值来代表这个值是否被设置。

package main
import (
    "bytes"
    "encoding/gob"
    "fmt"
    "log"
)
type Employee struct {
    
    
    Name    string
    Age     int
    Options gob.OptionalValue json:"options"
}
func main() {
    
    
    e := &Employee{
    
    
        Name: "John Doe",
        Age:  30,
        Options: gob.OptionalValue{
    
    
            IsSet: true,
            Value: "optional value",
        },
    }
    // Encode e to a buffer
    buf := new(bytes.Buffer)
    enc := gob.NewEncoder(buf)
    err := enc.Encode(e)
    if err != nil {
    
    
        log.Fatal("encode error:", err)
    }
    // Decode from the buffer
    dec := gob.NewDecoder(buf)
    var outEmployee Employee
    err = dec.Decode(&outEmployee)
    if err != nil {
    
    
        log.Fatal("decode error:", err)
    }
    fmt.Printf("Name: %s\nAge: %d\nOptions: %s\n",
        outEmployee.Name, outEmployee.Age, outEmployee.Options.Value)
}
// 运行结果:
// Name: John Doe
// Age: 30
// Options: optional value

猜你喜欢

转载自blog.csdn.net/BBinChina/article/details/129433702