Rust vs Go:常用语法对比(五)

题图来自 Rust vs Go 2023[1]

81. Round floating point number to integer

Declare integer y and initialize it with the rounded value of floating point number x . Ties (when the fractional part of x is exactly .5) must be rounded up (to positive infinity).

按规则取整

复制代码
package main

import (
 "fmt"
 "math"
)

func round(x float64) int {
 y := int(math.Floor(x + 0.5))
 return y
}

func main() {
 for _, x := range []float64{-1.1, -0.9, -0.5, -0.1, 0., 0.1, 0.5, 0.9, 1.1} {
  fmt.Printf("%5.1f %5d\n", x, round(x))
 }
}

 -1.1    -1
 -0.9    -1
 -0.5     0
 -0.1     0
  0.0     0
  0.1     0
  0.5     1
  0.9     1
  1.1     1

复制代码
fn main() {
    let x : f64 = 2.71828;
    let y = x.round() as i64;
    
    println!("{} {}", x, y);
}

2.71828 3

82. Count substring occurrences

统计子字符串出现次数

复制代码
package main

import (
 "fmt"
 "strings"
)

func main() {
 s := "Romaromamam"
 t := "mam"

 x := strings.Count(s, t)

 fmt.Println(x)
}

1


复制代码
fn main() {
    let s = "lorem ipsum lorem ipsum lorem ipsum lorem ipsum";
    let t = "ipsum";

    let c = s.matches(t).count();

    println!("{} occurrences", c);
}

Disjoint matches: overlapping occurrences are not counted.

4 occurrences

83. Regex with character repetition

Declare regular expression r matching strings "http", "htttp", "httttp", etc.

正则表达式匹配重复字符

复制代码
package main

import (
 "fmt"
 "regexp"
)

func main() {
 r := regexp.MustCompile("htt+p")

 for _, s := range []string{
  "hp",
  "htp",
  "http",
  "htttp",
  "httttp",
  "htttttp",
  "htttttp",
  "word htttp in a sentence",
 } {
  fmt.Println(s, "=>", r.MatchString(s))
 }
}

hp => false
htp => false
http => true
htttp => true
httttp => true
htttttp => true
htttttp => true
word htttp in a sentence => true

复制代码
extern crate regex;
use regex::Regex;

fn main() {
    let r = Regex::new(r"htt+p").unwrap();
    
    assert!(r.is_match("http"));
    assert!(r.is_match("htttp"));
    assert!(r.is_match("httttp"));
}

84. Count bits set in integer binary representation

Count number c of 1s in the integer i in base 2.

E.g. i=6 → c=2

计算十进制整型的二进制表示中 1的个数

复制代码
package main

import "fmt"

func PopCountUInt64(i uint64) (c int) {
 // bit population count, see
 // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
 i -= (i >> 1) & 0x5555555555555555
 i = (i>>2)&0x3333333333333333 + i&0x3333333333333333
 i += i >> 4
 i &= 0x0f0f0f0f0f0f0f0f
 i *= 0x0101010101010101
 return int(i >> 56)
}

func PopCountUInt32(i uint32) (n int) {
 // bit population count, see
 // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
 i -= (i >> 1) & 0x55555555
 i = (i>>2)&0x33333333 + i&0x33333333
 i += i >> 4
 i &= 0x0f0f0f0f
 i *= 0x01010101
 return int(i >> 24)
}

func main() {
 for i := uint64(0); i < 16; i++ {
  c := PopCountUInt64(i)
  fmt.Printf("%4d %04[1]b %d\n", i, c)
 }

 for i := uint32(0); i < 16; i++ {
  c := PopCountUInt32(i)
  fmt.Printf("%4d %04[1]b %d\n", i, c)
 }
}

   0 0000 0
   1 0001 1
   2 0010 1
   3 0011 2
   4 0100 1
   5 0101 2
   6 0110 2
   7 0111 3
   8 1000 1
   9 1001 2
  10 1010 2
  11 1011 3
  12 1100 2
  13 1101 3
  14 1110 3
  15 1111 4
   0 0000 0
   1 0001 1
   2 0010 1
   3 0011 2
   4 0100 1
   5 0101 2
   6 0110 2
   7 0111 3
   8 1000 1
   9 1001 2
  10 1010 2
  11 1011 3
  12 1100 2
  13 1101 3
  14 1110 3
  15 1111 4

This was useful only before go 1.9. See math/bits.OnesCount instead

or

复制代码
package main

import (
 "fmt"
 "math/bits"
)

func main() {
 for i := uint(0); i < 16; i++ {
  c := bits.OnesCount(i)
  fmt.Printf("%4d %04[1]b %d\n", i, c)
 }
}

   0 0000 0
   1 0001 1
   2 0010 1
   3 0011 2
   4 0100 1
   5 0101 2
   6 0110 2
   7 0111 3
   8 1000 1
   9 1001 2
  10 1010 2
  11 1011 3
  12 1100 2
  13 1101 3
  14 1110 3
  15 1111 4

复制代码
fn main() {
    println!("{}", 6usize.count_ones())
}

2

85. Check if integer addition will overflow

检查两个整型相加是否溢出

复制代码
package main

import (
 "fmt"
 "math"
)

func willAddOverflow(a, b int64) bool {
 return a > math.MaxInt64-b
}

func main() {

 fmt.Println(willAddOverflow(11111111111111111, 2))

}

false


复制代码
fn adding_will_overflow(x: usize, y: usize) -> bool {
    x.checked_add(y).is_none()
}

fn main() {
    {
        let (x, y) = (2345678, 9012345);

        let overflow = adding_will_overflow(x, y);

        println!(
            "{} + {} {}",
            x,
            y,
            if overflow {
                "overflows"
            } else {
                "doesn't overflow"
            }
        );
    }
    {
        let (x, y) = (2345678901, 9012345678);

        let overflow = adding_will_overflow(x, y);

        println!(
            "{} + {} {}",
            x,
            y,
            if overflow {
                "overflows"
            } else {
                "doesn't overflow"
            }
        );
    }
    {
        let (x, y) = (2345678901234, 9012345678901);

        let overflow = adding_will_overflow(x, y);

        println!(
            "{} + {} {}",
            x,
            y,
            if overflow {
                "overflows"
            } else {
                "doesn't overflow"
            }
        );
    }
    {
        let (x, y) = (23456789012345678, 90123456789012345);

        let overflow = adding_will_overflow(x, y);

        println!(
            "{} + {} {}",
            x,
            y,
            if overflow {
                "overflows"
            } else {
                "doesn't overflow"
            }
        );
    }
    {
        let (x, y) = (12345678901234567890, 9012345678901234567);

        let overflow = adding_will_overflow(x, y);

        println!(
            "{} + {} {}",
            x,
            y,
            if overflow {
                "overflows"
            } else {
                "doesn't overflow"
            }
        );
    }
}

2345678 + 9012345 doesn't overflow
2345678901 + 9012345678 doesn't overflow
2345678901234 + 9012345678901 doesn't overflow
23456789012345678 + 90123456789012345 doesn't overflow
12345678901234567890 + 9012345678901234567 overflows

86. Check if integer multiplication will overflow

检查整型相乘是否溢出

复制代码
package main

import (
 "fmt"
)

func multiplyWillOverflow(x, y uint64) bool {
 if x <= 1 || y <= 1 {
  return false
 }
 d := x * y
 return d/y != x
}

func main() {
 {
  var x, y uint64 = 2345, 6789
  if multiplyWillOverflow(x, y) {
   fmt.Println(x, "*", y, "overflows")
  } else {
   fmt.Println(x, "*", y, "doesn't overflow")
  }
 }
 {
  var x, y uint64 = 2345678, 9012345
  if multiplyWillOverflow(x, y) {
   fmt.Println(x, "*", y, "overflows")
  } else {
   fmt.Println(x, "*", y, "doesn't overflow")
  }
 }
 {
  var x, y uint64 = 2345678901, 9012345678
  if multiplyWillOverflow(x, y) {
   fmt.Println(x, "*", y, "overflows")
  } else {
   fmt.Println(x, "*", y, "doesn't overflow")
  }
 }
}

2345 * 6789 doesn't overflow
2345678 * 9012345 doesn't overflow
2345678901 * 9012345678 overflows

复制代码
fn main() {
    {
        let (x, y) = (2345, 6789);

        let overflow = multiply_will_overflow(x, y);

        println!(
            "{} * {} {}",
            x,
            y,
            if overflow {
                "overflows"
            } else {
                "doesn't overflow"
            }
        );
    }
    {
        let (x, y) = (2345678, 9012345);

        let overflow = multiply_will_overflow(x, y);

        println!(
            "{} * {} {}",
            x,
            y,
            if overflow {
                "overflows"
            } else {
                "doesn't overflow"
            }
        );
    }
    {
        let (x, y) = (2345678901, 9012345678);

        let overflow = multiply_will_overflow(x, y);

        println!(
            "{} * {} {}",
            x,
            y,
            if overflow {
                "overflows"
            } else {
                "doesn't overflow"
            }
        );
    }
}

fn multiply_will_overflow(x: i64, y: i64) -> bool {
    x.checked_mul(y).is_none()
}

2345 * 6789 doesn't overflow
2345678 * 9012345 doesn't overflow
2345678901 * 9012345678 overflows

87. Stop program

Exit immediately.

If some extra cleanup work is executed by the program runtime (not by the OS itself), describe it.

停止程序,立即退出。

复制代码
package main

import "os"

func main() {

 os.Exit(1)

 print(2222)
}

复制代码
fn main() {
    std::process::exit(1);
    println!("42");
}

88. Allocate 1M bytes

分配1M内存

复制代码
package main

import "fmt"

func main() {
 buf := make([]byte, 1000000)

 for i, b := range buf {
  if b != 0 {
   fmt.Println("Found unexpected value", b, "at position", i)
  }
 }
 fmt.Println("Buffer was correctly initialized with zero values.")
}

Buffer was correctly initialized with zero values.


复制代码
fn main() {
    let buf: Vec<u8> = Vec::with_capacity(1024 * 1024);
    println!("{:?}", buf.capacity());
}

1048576

89. Handle invalid argument

处理无效参数

复制代码
package main

import "fmt"

// NewSquareMatrix creates a N-by-N matrix
func NewSquareMatrix(N int) ([][]float64, error) {
 if N < 0 {
  return nil, fmt.Errorf("Invalid size %d: order cannot be negative", N)
 }
 matrix := make([][]float64, N)
 for i := range matrix {
  matrix[i] = make([]float64, N)
 }
 return matrix, nil
}

func main() {
 N1 := 3
 matrix1, err1 := NewSquareMatrix(N1)
 if err1 == nil {
  fmt.Println(matrix1)
 } else {
  fmt.Println(err1)
 }

 N2 := -2
 matrix2, err2 := NewSquareMatrix(N2)
 if err2 == nil {
  fmt.Println(matrix2)
 } else {
  fmt.Println(err2)
 }
}

[[0 0 0] [0 0 0] [0 0 0]]
Invalid size -2: order cannot be negative

复制代码
#[derive(Debug, PartialEq, Eq)]
enum CustomError { InvalidAnswer }

fn do_stuff(x: i32) -> Result<i32, CustomError> {
    if x != 42 {
%2

90. Read-only outside

外部只读

复制代码
type Foo struct {
 x int
}

func (f *Foo) X() int {
 return f.x
}

x is private, because it is not capitalized.
(*Foo).X is a public getter (a read accessor).

复制代码
struct Foo {
    x: usize
}

impl Foo {
    pub fn new(x: usize) -> Self {
        Foo { x }
    }

    pub fn x<'a>(&'a self) -> &'a usize {
        &self.x
    }
}

91. Load JSON file into struct

json转结构体

复制代码
package main

import "fmt"
import "io/ioutil"
import "encoding/json"

func readJSONFile() error {
 var x Person

 buffer, err := ioutil.ReadFile(filename)
 if err != nil {
  return err
 }
 err = json.Unmarshal(buffer, &x)
 if err != nil {
  return err
 }

 fmt.Println(x)
 return nil
}

func main() {
 err := readJSONFile()
 if err != nil {
  panic(err)
 }
}

type Person struct {
 FirstName string
 Age       int
}

const filename = "/tmp/data.json"

func init() {
 err := ioutil.WriteFile(filename, []byte(`
  {
   "FirstName":"Napoléon",
   "Age": 51 
  }`), 0644)
 if err != nil {
  panic(err)
 }
}

{Napoléon 51}

or

复制代码
package main

import (
 "encoding/json"
 "fmt"
 "io/ioutil"
 "os"
)

func readJSONFile() error {
 var x Person

 r, err := os.Open(filename)
 if err != nil {
  return err
 }
 decoder := json.NewDecoder(r)
 err = decoder.Decode(&x)
 if err != nil {
  return err
 }

 fmt.Println(x)
 return nil
}

func main() {
 err := readJSONFile()
 if err != nil {
  panic(err)
 }
}

type Person struct {
 FirstName string
 Age       int
}

const filename = "/tmp/data.json"

func init() {
 err := ioutil.WriteFile(filename, []byte(`
  {
   "FirstName":"Napoléon",
   "Age": 51 
  }`), 0644)
 if err != nil {
  panic(err)
 }
}

{Napoléon 51}


复制代码
#[macro_use] extern crate serde_derive;
extern crate serde_json;
use std::fs::File;
let x = ::serde_json::from_reader(File::open("data.json")?)?;

92. Save object into JSON file

将json对象写入文件

复制代码
package main

import "fmt"
import "io/ioutil"
import "encoding/json"

func writeJSONFile() error {
 x := Person{
  FirstName: "Napoléon",
  Age:       51,
 }

 buffer, err := json.MarshalIndent(x, "", "  ")
 if err != nil {
  return err
 }
 return ioutil.WriteFile(filename, buffer, 0644)
}

func main() {
 err := writeJSONFile()
 if err != nil {
  panic(err)
 }
 fmt.Println("Done.")
}

type Person struct {
 FirstName string
 Age       int
}

const filename = "/tmp/data.json"

json.MarshalIndent is more human-readable than json.Marshal.

Done.


复制代码
extern crate serde_json;
#[macro_use] extern crate serde_derive;

use std::fs::File;
::serde_json::to_writer(&File::create("data.json")?, &x)?

93. Pass a runnable procedure as parameter

Implement procedure control which receives one parameter f, and runs f.

以函数作为参数

复制代码
package main

import "fmt"

func main() {
 control(greet)
}

func control(f func()) {
 fmt.Println("Before f")
 f()
 fmt.Println("After f")
}

func greet() {
 fmt.Println("Hello, developers")
}

Go supports first class functions, higher-order functions, user-defined function types, function literals, and closures.

复制代码
Before f
Hello, developers
After f

复制代码
fn control(f: impl Fn()) {
    f();
}

fn hello() {
    println!("Hello,");
}

fn main() {
    control(hello);
    control(|| { println!("Is there anybody in there?"); });
}

Hello,
Is there anybody in there?

94. Print type of variable

打印变量的类型

复制代码
package main

import (
 "fmt"
 "os"
 "reflect"
)

func main() {
 var x interface{}

 x = "Hello"
 fmt.Println(reflect.TypeOf(x))

 x = 4
 fmt.Println(reflect.TypeOf(x))

 x = os.NewFile(0777, "foobar.txt")
 fmt.Println(reflect.TypeOf(x))
}

string
int
*os.File

or

复制代码
package main

import (
 "fmt"
 "os"
)

func main() {
 var x interface{}

 x = "Hello"
 fmt.Printf("%T", x)
 fmt.Println()

 x = 4
 fmt.Printf("%T", x)
 fmt.Println()

 x = os.NewFile(0777, "foobar.txt")
 fmt.Printf("%T", x)
 fmt.Println()
}

string
int
*os.File

复制代码
#![feature(core_intrinsics)]

fn type_of<T>(_: &T) -> String {
    format!("{}", std::intrinsics::type_name::<T>())
}

fn main() {
    let x: i32 = 1;
    println!("{}", type_of(&x));
}

i32

95. Get file size

获取文件的大小

复制代码
package main

import (
 "fmt"
 "io/ioutil"
 "os"
)

func main() {
 err := printSize("file.txt")
 if err != nil {
  panic(err)
 }
}

func printSize(path string) error {
 info, err := os.Stat(path)
 if err != nil {
  return err
 }
 x := info.Size()

 fmt.Println(x)
 return nil
}

func init() {
 // The file will only contains the characters "Hello", no newlines.
 buffer := []byte("Hello")
 err := ioutil.WriteFile("file.txt", buffer, 0644)
 if err != nil {
  panic(err)
 }
}

5


复制代码
use std::fs;

fn filesize(path: &str) -> Result<u64, std::io::Error> {
    let x = fs::metadata(path)?.len();
    Ok(x)
}

fn main() {
    let path = "/etc/hosts";
    let x = filesize(path);
    println!("{}: {:?} bytes", path, x.unwrap());
}

/etc/hosts: 150 bytes

or

复制代码
use std::path::Path;

fn filesize(path: &std::path::Path) -> Result<u64, std::io::Error> {
    let x = path.metadata()?.len();
    Ok(x)
}

fn main() {
    let path = Path::new("/etc/hosts");
    let x = filesize(path);
    println!("{:?}: {:?} bytes", path, x.unwrap());
}

"/etc/hosts": 150 bytes

96. Check string prefix

Set boolean b to true if string s starts with prefix prefix, false otherwise.

检查两个字符串前缀是否一致

复制代码
package main

import (
 "fmt"
 "strings"
)

func check(s, prefix string) {

 b := strings.HasPrefix(s, prefix)

 if b {
  fmt.Println(s, "starts with", prefix)
 } else {
  fmt.Println(s, "doesn't start with", prefix)
 }
}

func main() {
 check("bar", "foo")
 check("foobar", "foo")
}

bar doesn't start with foo
foobar starts with foo

复制代码
fn main() {
    let s = "bananas";
    let prefix = "bana";

    let b = s.starts_with(prefix);

    println!("{:?}", b);
}

true

97. Check string suffix

Set boolean b to true if string s ends with string suffix, false otherwise.

检查字符串后缀

复制代码
package main

import (
 "fmt"
 "strings"
)

func check(s, suffix string) {

 b := strings.HasSuffix(s, suffix)

 if b {
  fmt.Println(s, "ends with", suffix)
 } else {
  fmt.Println(s, "doesn't end with", suffix)
 }
}

func main() {
 check("foo", "bar")
 check("foobar", "bar")
}

foo doesn't end with bar
foobar ends with bar

复制代码
fn main() {
    let s = "bananas";
    let suffix = "nas";

    let b = s.ends_with(suffix);

    println!("{:?}", b);
}

true

98. Epoch seconds to date object

Convert a timestamp ts (number of seconds in epoch-time) to a date with time d. E.g. 0 -> 1970-01-01 00:00:00

时间戳转日期

复制代码
package main

import (
 "fmt"
 "time"
)

func main() {
 ts := int64(1451606400)
 d := time.Unix(ts, 0)

 fmt.Println(d)
}

2016-01-01 00:00:00 +0000 UTC


复制代码
extern crate chrono;
use chrono::prelude::*;

fn main() {
    let ts = 1451606400;
    let d = NaiveDateTime::from_timestamp(ts, 0);
    println!("{}", d);
}

2016-01-01 00:00:00

99. Format date YYYY-MM-DD

Assign to string x the value of fields (year, month, day) of date d, in format YYYY-MM-DD.

时间格式转换

复制代码
package main

import (
 "fmt"
 "time"
)

func main() {
 d := time.Now()
 x := d.Format("2006-01-02")
 fmt.Println(x)

 // The output may be "2009-11-10" because the Playground's clock is fixed in the past.
}

2009-11-10


复制代码
extern crate chrono;

use chrono::prelude::*;

fn main() {
    println!("{}", Utc::today().format("%Y-%m-%d"))
}

2021-07-17

100. Sort by a comparator

Sort elements of array-like collection items, using a comparator c.

根据某个字段排序

复制代码
package main

import "fmt"
import "sort"

type Item struct {
 label string
 p     int
 lang  string
}

// c returns true if x is "inferior to" y (in a custom way)
func c(x, y Item) bool {
 return x.p < y.p
}

type ItemCSorter []Item

func (s ItemCSorter) Len() int           { return len(s) }
func (s ItemCSorter) Less(i, j int) bool { return c(s[i], s[j]) }
func (s ItemCSorter) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

func sortItems(items []Item) {
 sorter := ItemCSorter(items)
 sort.Sort(sorter)
}

func main() {
 items := []Item{
  {"twelve", 12, "english"},
  {"six", 6, "english"},
  {"eleven", 11, "english"},
  {"zero", 0, "english"},
  {"two", 2, "english"},
 }
 fmt.Println("Unsorted: ", items)
 sortItems(items)
 fmt.Println("Sorted: ", items)
}

c has type func(Item, Item) bool.

复制代码
Unsorted:  [{twelve 12 english} {six 6 english} {eleven 11 english} {zero 0 english} {two 2 english}]
Sorted:  [{zero 0 english} {two 2 english} {six 6 english} {eleven 11 english} {twelve 12 english}]

or

复制代码
package main

import "fmt"
import "sort"

type Item struct {
 label string
 p     int
 lang  string
}

type ItemsSorter struct {
 items []Item
 c     func(x, y Item) bool
}

func (s ItemsSorter) Len() int           { return len(s.items) }
func (s ItemsSorter) Less(i, j int) bool { return s.c(s.items[i], s.items[j]) }
func (s ItemsSorter) Swap(i, j int)      { s.items[i], s.items[j] = s.items[j], s.items[i] }

func sortItems(items []Item, c func(x, y Item) bool) {
 sorter := ItemsSorter{
  items,
  c,
 }
 sort.Sort(sorter)
}

func main() {
 items := []Item{
  {"twelve", 12, "english"},
  {"six", 6, "english"},
  {"eleven", 11, "english"},
  {"zero", 0, "english"},
  {"two", 2, "english"},
 }
 fmt.Println("Unsorted: ", items)

 c := func(x, y Item) bool {
  return x.p < y.p
 }
 sortItems(items, c)

 fmt.Println("Sorted: ", items)
}

ItemsSorter contains c, which can be any comparator decided at runtime.

复制代码
Unsorted:  [{twelve 12 english} {six 6 english} {eleven 11 english} {zero 0 english} {two 2 english}]
Sorted:  [{zero 0 english} {two 2 english} {six 6 english} {eleven 11 english} {twelve 12 english}]

or

复制代码
package main

import "fmt"
import "sort"

type Item struct {
 label string
 p     int
 lang  string
}

// c returns true if x is "inferior to" y (in a custom way)
func c(x, y Item) bool {
 return x.p < y.p
}

func main() {
 items := []Item{
  {"twelve", 12, "english"},
  {"six", 6, "english"},
  {"eleven", 11, "english"},
  {"zero", 0, "english"},
  {"two", 2, "english"},
 }
 fmt.Println("Unsorted: ", items)
 
 sort.Slice(items, func(i, j int) bool {
  return c(items[i], items[j])
 })
 
 fmt.Println("Sorted: ", items)
}

Since Go 1.8, a single func parameter is sufficient to sort a slice.

复制代码
Unsorted:  [{twelve 12 english} {six 6 english} {eleven 11 english} {zero 0 english} {two 2 english}]
Sorted:  [{zero 0 english} {two 2 english} {six 6 english} {eleven 11 english} {twelve 12 english}]

复制代码
fn main() {
    let mut items = [1, 7, 5, 2, 3];
    items.sort_by(i32::cmp);
    println!("{:?}", items);
}

[1, 2, 3, 5, 7]

参考资料

1

Rust vs Go 2023: https://arkiana.com/rust-vs-go/

本文由mdnice多平台发布

相关推荐
极客智谷26 分钟前
深入理解Java线程池:从原理到实战的完整指南
java·后端
我的耳机没电了27 分钟前
mySpace项目遇到的问题
后端
陈随易1 小时前
长跑8年,Node.js框架Koa v3.0终发布
前端·后端·程序员
lovebugs1 小时前
Redis的高性能奥秘:深入解析IO多路复用与单线程事件驱动模型
redis·后端·面试
bug菌1 小时前
面十年开发候选人被反问:当类被标注为@Service后,会有什么好处?我...🫨
spring boot·后端·spring
田园Coder1 小时前
Spring之IoC控制反转
后端
bxlj2 小时前
RocketMQ消息类型
后端
Asthenia04122 小时前
从NIO到Netty:盘点那些零拷贝解决方案
后端
米开朗基杨2 小时前
Cursor 最强竞争对手来了,专治复杂大项目,免费一个月
前端·后端
Asthenia04122 小时前
anal到Elasticsearch数据一致性保障分析(基于RocketMQ)
后端