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

alt

题目来自 Golang vs. Rust: Which Programming Language To Choose in 2023?[1]


141. Iterate in sequence over two lists

Iterate in sequence over the elements of the list items1 then items2. For each iteration print the element.

依次迭代两个列表 依次迭代列表项1和项2的元素。每次迭代打印元素。

package main

import (
 "fmt"
)

func main() {
 items1 := []string{"a""b""c"}
 items2 := []string{"A""B""C"}

 for _, v := range items1 {
  fmt.Println(v)
 }
 for _, v := range items2 {
  fmt.Println(v)
 }
}

a
b
c
A
B
C

fn main() {
    let item1 = vec!["1""2""3"];
    let item2 = vec!["a""b""c"];
    for i in item1.iter().chain(item2.iter()) {
        print!("{} ", i);
    }
}

1 2 3 a b c


142. Hexadecimal digits of an integer

Assign to string s the hexadecimal representation (base 16) of integer x.
E.g. 999 -> "3e7"

将整数x的十六进制表示(16进制)赋给字符串s。

package main

import "fmt"
import "strconv"

func main() {
 x := int64(999)
 s := strconv.FormatInt(x, 16)

 fmt.Println(s)
}

3e7

or

package main

import (
 "fmt"
 "math/big"
)

func main() {
 x := big.NewInt(999)
 s := fmt.Sprintf("%x", x)

 fmt.Println(s)
}

3e7


fn main() {
    let x = 999;

    let s = format!("{:X}", x);
    println!("{}", s);

    let s = format!("{:x}", x);
    println!("{}", s);
}

{:X} produces uppercase hex. {:x} produces lowercase hex.

3E7
3e7

143. Iterate alternatively over two lists

Iterate alternatively over the elements of the list items1 and items2. For each iteration, print the element.
Explain what happens if items1 and items2 have different size.

交替迭代两个列表

package main

import (
 "fmt"
)

func main() {
 items1 := []string{"a""b"}
 items2 := []string{"A""B""C"}

 for i := 0; i < len(items1) || i < len(items2); i++ {
  if i < len(items1) {
   fmt.Println(items1[i])
  }
  if i < len(items2) {
   fmt.Println(items2[i])
  }
 }
}

a
A
b
B
C

extern crate itertools;
use itertools::izip;

fn main() {
    let items1 = [51525];
    let items2 = [102030];

    for pair in izip!(&items1, &items2) {
        println!("{}", pair.0);
        println!("{}", pair.1);
    }
}

5
10
15
20
25
30

144. Check if file exists

Set boolean b to true if file at path fp exists on filesystem; false otherwise.
Beware that you should never do this and then in the next instruction assume the result is still valid, this is a race condition on any multitasking OS.

检查文件是否存在

package main

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

func main() {
 fp := "foo.txt"
 _, err := os.Stat(fp)
 b := !os.IsNotExist(err)
 fmt.Println(fp, "exists:", b)

 fp = "bar.txt"
 _, err = os.Stat(fp)
 b = !os.IsNotExist(err)
 fmt.Println(fp, "exists:", b)
}

func init() {
 ioutil.WriteFile("foo.txt", []byte(`abc`), 0644)
}

There's no specific existence check func in standard library, so we have to inspect an error return value.

foo.txt exists: true
bar.txt exists: false

fn main() {
    let fp = "/etc/hosts";
    let b = std::path::Path::new(fp).exists();
    println!("{}: {}", fp, b);

    let fp = "/etc/kittens";
    let b = std::path::Path::new(fp).exists();
    println!("{}: {}", fp, b);
}

/etc/hosts: true
/etc/kittens: false

145. Print log line with datetime

Print message msg, prepended by current date and time.
Explain what behavior is idiomatic: to stdout or stderr, and what the date format is.

打印带时间的日志

package main

import "log"

func main() {
 msg := "Hello, playground"
 log.Println(msg)

 // The date is fixed in the past in the Playground, never mind.
}

// See http://www.programming-idioms.org/idiom/145/print-log-line-with-date/1815/go

2009/11/10 23:00:00 Hello, playground


fn main() {
    let msg = "Hello";
    eprintln!("[{}] {}", humantime::format_rfc3339_seconds(std::time::SystemTime::now()), msg);
}

[2021-07-17T07:14:03Z] Hello


146. Convert string to floating point number

Extract floating point value f from its string representation s

字符串转换为浮点型

package main

import (
 "fmt"
 "strconv"
)

func main() {
 s := "3.1415926535"

 f, err := strconv.ParseFloat(s, 64)
 fmt.Printf("%T, %v, err=%v\n", f, f, err)
}

//
// http://www.programming-idioms.org/idiom/146/convert-string-to-floating-point-number/1819/go
//

float64, 3.1415926535, err=<nil>


fn main() {
    let s = "3.14159265359";
    let f = s.parse::<f32>().unwrap();
    
    println!("{}² = {}" , f, f * f);
}

3.1415927² = 9.869605

or

fn main() {
    let s = "3.14159265359";
    let f: f32 = s.parse().unwrap();

    println!("{}² = {}", f, f * f);
}

3.1415927² = 9.869605


147. Remove all non-ASCII characters

Create string t from string s, keeping only ASCII characters

移除所有的非ASCII字符

package main

import (
 "fmt"
 "regexp"
)

func main() {
 s := "dæmi : пример : příklad : thí dụ"

 re := regexp.MustCompile("[[:^ascii:]]")
 t := re.ReplaceAllLiteralString(s, "")

 fmt.Println(t)
}

dmi : : pklad : th d

or

package main

import (
 "fmt"
 "strings"
 "unicode"
)

func main() {
 s := "5#∑∂ƒ∞645eyfu"
 t := strings.Map(func(r rune) rune {
  if r > unicode.MaxASCII {
   return -1
  }
  return r
 }, s)
 fmt.Println(t)
}

5#645eyfu


fn main() {
    println!("{}""do👍ot".replace(|c: char| !c.is_ascii(), ""))
}

doot

or

fn main() {
    println!("{}""do👍ot".replace(|c: char| !c.is_ascii(), ""))
}

doot


148. Read list of integers from stdin

Read a list of integer numbers from the standard input, until EOF.

从stdin(标准输入)中读取整数列表

package main

import (
 "bufio"
 "fmt"
 "log"
 "strconv"
 "strings"
)

func main() {
 var ints []int
 s := bufio.NewScanner(osStdin)
 s.Split(bufio.ScanWords)
 for s.Scan() {
  i, err := strconv.Atoi(s.Text())
  if err == nil {
   ints = append(ints, i)
  }
 }
 if err := s.Err(); err != nil {
  log.Fatal(err)
 }
 fmt.Println(ints)
}

// osStdin simulates os.Stdin
var osStdin = strings.NewReader(`
11
22
33  `
)

[11 22 33]


use std::{
    io::{self, Read},
    str::FromStr,
};

// dummy io::stdin
fn io_stdin() -> impl Read {
    "123
456
789"

    .as_bytes()
}

fn main() -> io::Result<()> {
    let mut string = String::new();
    io_stdin().read_to_string(&mut string)?;
    let result = string
        .lines()
        .map(i32::from_str)
        .collect::<Result<Vec<_>, _>>();
    println!("{:#?}", result);
    Ok(())
}
Ok(
    [
        123,
        456,
        789,
    ],
)

150. Remove trailing slash

Remove last character from string p, if this character is a slash /.

去除末尾的 /

package main

import (
 "fmt"
 "strings"
)

func main() {
 p := "/usr/bin/"

 p = strings.TrimSuffix(p, "/")

 fmt.Println(p)
}

/usr/bin


fn main() {
    let mut p = String::from("Dddd/");
    if p.ends_with('/') {
        p.pop();
    }
    println!("{}", p);
}

Dddd


151. Remove string trailing path separator

Remove last character from string p, if this character is the file path separator of current platform.
Note that this also transforms unix root path "/" into the empty string!

删除字符串尾部路径分隔符

package main

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

func main() {
 p := somePath()
 fmt.Println(p)

 sep := fmt.Sprintf("%c", os.PathSeparator)
 p = strings.TrimSuffix(p, sep)

 fmt.Println(p)
}

func somePath() string {
 dir, err := ioutil.TempDir("""")
 if err != nil {
  panic(err)
 }
 p := fmt.Sprintf("%s%c%s%c", dir, os.PathSeparator, "foobar", os.PathSeparator)
 return p
}

/tmp/067319278/foobar/
/tmp/067319278/foobar

or

package main

import (
 "fmt"
 "io/ioutil"
 "os"
 "path/filepath"
 "strings"
)

func main() {
 p := somePath()
 fmt.Println(p)

 sep := fmt.Sprintf("%c", filepath.Separator)
 p = strings.TrimSuffix(p, sep)

 fmt.Println(p)
}

func somePath() string {
 dir, err := ioutil.TempDir("""")
 if err != nil {
  panic(err)
 }
 p := fmt.Sprintf("%s%c%s%c", dir, os.PathSeparator, "foobar", os.PathSeparator)
 return p
}
/tmp/065654753/foobar/
/tmp/065654753/foobar

fn main() {
    {
        let p = "/tmp/";

        let p = if ::std::path::is_separator(p.chars().last().unwrap()) {
            &p[0..p.len() - 1]
        } else {
            p
        };

        println!("{}", p);
    }
    
    {
        let p = "/tmp";

        let p = if ::std::path::is_separator(p.chars().last().unwrap()) {
            &p[0..p.len() - 1]
        } else {
            p
        };

        println!("{}", p);
    }
}
/tmp
/tmp

or

fn main() {
    {
        let mut p = "/tmp/";

        p = p.strip_suffix(std::path::is_separator).unwrap_or(p);

        println!("{}", p);
    }
    
    {
        let mut p = "/tmp";

        p = p.strip_suffix(std::path::is_separator).unwrap_or(p);

        println!("{}", p);
    }
}
/tmp
/tmp

152. Turn a character into a string

Create string s containing only the character c.

将字符转换成字符串

package main

import (
 "fmt"
 "os"
)

func main() {
 var c rune = os.PathSeparator
 fmt.Printf("%c \n", c)

 s := fmt.Sprintf("%c", c)
 fmt.Printf("%#v \n", s)
}


"/" 

fn main() {
    let c = 'a';
    
    let s = c.to_string();
    
    println!("{}", s);
}

a


153. Concatenate string with integer

Create string t as the concatenation of string s and integer i.

连接字符串和整数

package main

import (
 "fmt"
)

func main() {
 s := "Hello"
 i := 123

 t := fmt.Sprintf("%s%d", s, i)

 fmt.Println(t)
}

Hello123


fn main() {
    let s = "Foo";
    let i = 1;
    let t = format!("{}{}", s, i);
    
    println!("{}" , t);
}

Foo1


154. Halfway between two hex color codes

Find color c, the average between colors c1, c2.
c, c1, c2 are strings of hex color codes: 7 chars, beginning with a number sign # . Assume linear computations, ignore gamma corrections.

求两个十六进制颜色代码的中间值

package main

import (
 "fmt"
 "strconv"
 "strings"
)

// For concision, halfway assume valid inputs.
// Caller must have explicitly checked that c1, c2 are well-formed color codes.
func halfway(c1, c2 string) string {
 r1, _ := strconv.ParseInt(c1[1:3], 160)
 r2, _ := strconv.ParseInt(c2[1:3], 160)
 r := (r1 + r2) / 2

 g1, _ := strconv.ParseInt(c1[3:5], 160)
 g2, _ := strconv.ParseInt(c2[3:5], 160)
 g := (g1 + g2) / 2

 b1, _ := strconv.ParseInt(c1[5:7], 160)
 b2, _ := strconv.ParseInt(c2[5:7], 160)
 b := (b1 + b2) / 2

 c := fmt.Sprintf("#%02X%02X%02X", r, g, b)
 return c
}

func main() {
 c1 := "#15293E"
 c2 := "#012549"

 if err := checkFormat(c1); err != nil {
  panic(fmt.Errorf("Wrong input %q: %v", c1, err))
 }
 if err := checkFormat(c2); err != nil {
  panic(fmt.Errorf("Wrong input %q: %v", c2, err))
 }

 c := halfway(c1, c2)
 fmt.Println("The average of", c1, "and", c2, "is", c)
}

func checkFormat(color string) error {
 if len(color) != 7 {
  return fmt.Errorf("Hex colors have exactly 7 chars")
 }
 if color[0] != '#' {
  return fmt.Errorf("Hex colors start with #")
 }
 isNotDigit := func(c rune) bool { return (c < '0' || c > '9') && (c < 'a' || c > 'f') }
 if strings.IndexFunc(strings.ToLower(color[1:]), isNotDigit) != -1 {
  return fmt.Errorf("Forbidden char")
 }
 return nil
}

The average of #15293E and #012549 is #0B2743

package main

import (
 "fmt"
 "strconv"
 "strings"
)

// For concision, halfway assume valid inputs.
// Caller must have explicitly checked that c1, c2 are well-formed color codes.
func halfway(c1, c2 string) string {
 var buf [7]byte
 buf[0] = '#'
 for i := 0; i < 3; i++ {
  sub1 := c1[1+2*i : 3+2*i]
  sub2 := c2[1+2*i : 3+2*i]
  v1, _ := strconv.ParseInt(sub1, 160)
  v2, _ := strconv.ParseInt(sub2, 160)
  v := (v1 + v2) / 2
  sub := fmt.Sprintf("%02X", v)
  copy(buf[1+2*i:3+2*i], sub)
 }
 c := string(buf[:])

 return c
}

func main() {
 c1 := "#15293E"
 c2 := "#012549"

 if err := checkFormat(c1); err != nil {
  panic(fmt.Errorf("Wrong input %q: %v", c1, err))
 }
 if err := checkFormat(c2); err != nil {
  panic(fmt.Errorf("Wrong input %q: %v", c2, err))
 }

 c := halfway(c1, c2)
 fmt.Println("The average of", c1, "and", c2, "is", c)
}

func checkFormat(color string) error {
 if len(color) != 7 {
  return fmt.Errorf("Hex colors have exactly 7 chars")
 }
 if color[0] != '#' {
  return fmt.Errorf("Hex colors start with #")
 }
 isNotDigit := func(c rune) bool { return (c < '0' || c > '9') && (c < 'a' || c > 'f') }
 if strings.IndexFunc(strings.ToLower(color[1:]), isNotDigit) != -1 {
  return fmt.Errorf("Forbidden char")
 }
 return nil
}

The average of #15293E and #012549 is #0B2743


use std::str::FromStr;
use std::fmt;

#[derive(Debug)]
struct Colour {
    r: u8,
    g: u8,
    b: u8
}

#[derive(Debug)]
enum ColourError {
    MissingHash,
    InvalidRed,
    InvalidGreen,
    InvalidBlue
}

impl fmt::Display for Colour {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "#{:02x}{:02x}{:02x}"self.r, self.g, self.b)
    }
}

impl FromStr for Colour {
    type Err = ColourError;
    
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if !s.starts_with('#') {
            Err(ColourError::MissingHash)
        } else {
            Ok(Colour {
                r: u8::from_str_radix(&s[1..3], 16).map_err(|_| ColourError::InvalidRed)?,
                g: u8::from_str_radix(&s[3..5], 16).map_err(|_| ColourError::InvalidGreen)?,
                b: u8::from_str_radix(&s[5..7], 16).map_err(|_| ColourError::InvalidBlue)?
            })
        }
    }
}

fn mid_colour(c1: &str, c2: &str) -> Result<String, ColourError> {
    let c1 = c1.parse::<Colour>()?;
    let c2 = c2.parse::<Colour>()?;
    let c = Colour {
        r: (((c1.r as u16) + (c2.r as u16))/2as u8,
        g: (((c1.g as u16) + (c2.g as u16))/2as u8,
        b: (((c1.b as u16) + (c2.b as u16))/2as u8
    };
    Ok(format!("{}", c))
}

fn main() {
    println!("{}", mid_colour("#15293E""#012549").unwrap())
}

#0b2743


155. Delete file

Delete from filesystem the file having path filepath.

删除文件

package main

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

func main() {
 for _, filepath := range []string{
  "/tmp/foo.txt",
  "/tmp/bar.txt",
  "/tmp/foo.txt",
 } {
  err := os.Remove(filepath)
  if err == nil {
   fmt.Println("Removed", filepath)
  } else {
   fmt.Fprintln(os.Stderr, err)
  }
 }
}

func init() {
 err := ioutil.WriteFile("/tmp/foo.txt", []byte(`abc`), 0644)
 if err != nil {
  panic(err)
 }
}
Removed /tmp/foo.txt
remove /tmp/bar.txt: no such file or directory
remove /tmp/foo.txt: no such file or directory

use std::fs;

fn main() {
    let filepath = "/tmp/abc";

    println!("Creating {}", filepath);
    let _file = fs::File::create(filepath);

    let b = std::path::Path::new(filepath).exists();
    println!("{} exists: {}", filepath, b);

    println!("Deleting {}", filepath);
    let r = fs::remove_file(filepath);
    println!("{:?}", r);

    let b = std::path::Path::new(filepath).exists();
    println!("{} exists: {}", filepath, b);
}
Creating /tmp/abc
/tmp/abc exists: true
Deleting /tmp/abc
Ok(())
/tmp/abc exists: false

156. Format integer with zero-padding

Assign to string s the value of integer i in 3 decimal digits. Pad with zeros if i < 100. Keep all digits if i ≥ 1000.

用零填充格式化整数

package main

import (
 "fmt"
)

func main() {
 for _, i := range []int{
  0,
  8,
  64,
  256,
  2048,
 } {
  s := fmt.Sprintf("%03d", i)
  fmt.Println(s)
 }
}

000
008
064
256
2048

fn main() {
    let i = 1;
    let s = format!("{:03}", i);
    
    println!("{}", s);
    
    
    let i = 1000;
    let s = format!("{:03}", i);
    
    println!("{}", s);
}
001
1000

157. Declare constant string

Initialize a constant planet with string value "Earth".

声明常量字符串

package main

import (
 "fmt"
)

const planet = "Earth"

func main() {
 fmt.Println("We live on planet", planet)
}

We live on planet Earth


fn main() {
    const PLANET: &str = "Earth";
    
    println!("{}", PLANET);
}

Earth


158. Random sublist

Create a new list y from randomly picking exactly k elements from list x.

It is assumed that x has at least k elements. Each element must have same probability to be picked. Each element from x must be picked at most once. Explain if the original ordering is preserved or not.

随机子列表

package main

import (
 "fmt"
 "math/rand"
)

func main() {
 type T string

 x := []T{"Alice""Bob""Carol""Dan""Eve""Frank""Grace""Heidi"}
 k := 4

 y := make([]T, k)
 perm := rand.Perm(len(x))
 for i, v := range perm[:k] {
  y[i] = x[v]
 }

 fmt.Printf("%q", y)
}

["Frank" "Eve" "Carol" "Grace"]


use rand::prelude::*;
let mut rng = &mut rand::thread_rng();
let y = x.choose_multiple(&mut rng, k).cloned().collect::<Vec<_>>();

159. Trie

Define a Trie data structure, where entries have an associated value. (Not all nodes are entries)

前缀树/字典树

package main

import (
 "fmt"
 "unicode/utf8"
)

type Trie struct {
 c        rune
 children map[rune]*Trie
 isLeaf   bool
 value    V
}

type V int

func main() {
 t := NewTrie(0)
 for s, v := range map[string]V{
  "to":  7,
  "tea"3,
  "ted"4,
  "ten"12,
  "A":   15,
  "i":   11,
  "in":  5,
  "inn"9,
 } {
  t.insert(s, v)
 }
 fmt.Println(t.startsWith("te"""))
}

func NewTrie(c rune) *Trie {
 t := new(Trie)
 t.c = c
 t.children = map[rune]*Trie{}
 return t
}

func (t *Trie) insert(s string, value V) {
 if s == "" {
  t.isLeaf = true
  t.value = value
  return
 }
 c, tail := cut(s)
 child, exists := t.children[c]
 if !exists {
  child = NewTrie(c)
  t.children[c] = child
 }
 child.insert(tail, value)
}

func (t *Trie) startsWith(p string, accu string) []string {
 if t == nil {
  return nil
 }
 if p == "" {
  var result []string
  if t.isLeaf {
   result = append(result, accu)
  }
  for c, child := range t.children {
   rec := child.startsWith("", accu+string(c))
   result = append(result, rec...)
  }
  return result
 }
 c, tail := cut(p)
 return t.children[c].startsWith(tail, accu+string(c))
}

func cut(s string) (head rune, tail string) {
 r, size := utf8.DecodeRuneInString(s)
 return r, s[size:]
}

[ten tea ted]


struct Trie {
    val: String,
    nodes: Vec<Trie>
}

160. Detect if 32-bit or 64-bit architecture

Execute f32() if platform is 32-bit, or f64() if platform is 64-bit.
This can be either a compile-time condition (depending on target) or a runtime detection.

检测是32位还是64位架构

package main

import (
 "fmt"
 "strconv"
)

func main() {
 if strconv.IntSize == 32 {
  f32()
 }
 if strconv.IntSize == 64 {
  f64()
 }
}

func f32() {
 fmt.Println("I am 32-bit")
}

func f64() {
 fmt.Println("I am 64-bit")
}

I am 64-bit


fn main() {
    match std::mem::size_of::<&char>() {
        4 => f32(),
        8 => f64(),
        _ => {}
    }
}

fn f32() {
    println!("I am 32-bit");
}

fn f64() {
    println!("I am 64-bit");
}

I am 64-bit


参考资料

[1]

Golang vs. Rust: Which Programming Language To Choose in 2023?: https://www.trio.dev/blog/golang-vs-rust

本文由 mdnice 多平台发布

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值