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

题目来自 Rust Vs Go: Which Language Is Better For Developing High-Performance Applications?[1]

202. Sum of squares

Calculate the sum of squares s of data, an array of floating point values.

计算平方和

复制代码
package main

import (
 "math"
)

func main() {
 data := []float64{0.06, 0.82, -0.01, -0.34, -0.55}
 var s float64
 for _, d := range data {
  s += math.Pow(d, 2)
 }
 println(s)
}

+1.094200e+000


复制代码
fn main() {
    let data: Vec<f32> = vec![2.0, 3.5, 4.0];

    let s = data.iter().map(|x| x.powi(2)).sum::<f32>();

    println!("{}", s);
}

32.25

205. Get an environment variable

Read an environment variable with the name "FOO" and assign it to the string variable foo. If it does not exist or if the system does not support environment variables, assign a value of "none".

获取环境变量

复制代码
package main

import (
 "fmt"
 "os"
)

func main() {
 foo, ok := os.LookupEnv("FOO")
 if !ok {
  foo = "none"
 }

 fmt.Println(foo)
}

none

or

复制代码
package main

import (
 "fmt"
 "os"
)

func main() {
 foo := os.Getenv("FOO")
 if foo == "" {
  foo = "none"
 }

 fmt.Println(foo)
}

none


复制代码
use std::env;

fn main() {
    let foo;
    match env::var("FOO") {
        Ok(val) => foo = val,
        Err(_e) => foo = "none".to_string(),
    }
    println!("{}", foo);
    
    let user;
    match env::var("USER") {
        Ok(val) => user = val,
        Err(_e) => user = "none".to_string(),
    }
    println!("{}", user);
}

none
playground

or

复制代码
use std::env;

fn main() {
    let foo = env::var("FOO").unwrap_or("none".to_string());
    println!("{}", foo);

    let user = env::var("USER").unwrap_or("none".to_string());
    println!("{}", user);
}

none
playground

or

复制代码
use std::env;

fn main() {
    let foo = match env::var("FOO") {
        Ok(val) => val,
        Err(_e) => "none".to_string(),
    };
    println!("{}", foo);

    let user = match env::var("USER") {
        Ok(val) => val,
        Err(_e) => "none".to_string(),
    };
    println!("{}", user);
}

none
playground

or

复制代码
use std::env;
if let Ok(tnt_root) = env::var("TNT_ROOT") {
     //
}

206. Switch statement with strings

Execute different procedures foo, bar, baz and barfl if the string str contains the name of the respective procedure. Do it in a way natural to the language.

switch语句

复制代码
package main

import (
 "fmt"
)

func main() {
 str := "baz"

 switch str {
 case "foo":
  foo()
 case "bar":
  bar()
 case "baz":
  baz()
 case "barfl":
  barfl()
 }
}

func foo() {
 fmt.Println("Called foo")
}

func bar() {
 fmt.Println("Called bar")
}

func baz() {
 fmt.Println("Called baz")
}

func barfl() {
 fmt.Println("Called barfl")
}

Called baz


复制代码
fn main() {
    fn foo() {}
    fn bar() {}
    fn baz() {}
    fn barfl() {}
    let str_ = "x";
    match str_ {
        "foo" => foo(),
        "bar" => bar(),
        "baz" => baz(),
        "barfl" => barfl(),
        _ => {}
    }
}

207. Allocate a list that is automatically deallocated

Allocate a list a containing n elements (n assumed to be too large for a stack) that is automatically deallocated when the program exits the scope it is declared in.

分配一个自动解除分配的列表

复制代码
package main

import (
 "fmt"
)

type T byte

func main() {
 n := 10_000_000
 a := make([]T, n)
 fmt.Println(len(a))
}

Elements have type T. a is garbage-collected after the program exits its scope, unless we let it "escape" by taking its reference. The runtime decides if a lives in the stack on in the heap.

10000000


复制代码
let a = vec![0; n];

Heap allocations are deallocated when the variable goes out of scope.

208. Formula with arrays

Given the arrays a,b,c,d of equal length and the scalar e, calculate a = e*(a+b*c+cos(d)). Store the results in a.

对数组元素进行运算

复制代码
package main

import (
 "fmt"
 "math"
)

func applyFormula(a, b, c, d []float64, e float64) {
 for i, v := range a {
  a[i] = e * (v + b[i] + c[i] + math.Cos(d[i]))
 }
}

func main() {
 a := []float64{1, 2, 3, 4}
 b := []float64{5.5, 6.6, 7.7, 8.8}
 c := []float64{9, 10, 11, 12}
 d := []float64{13, 14, 15, 16}
 e := 42.0

 fmt.Println("a is    ", a)
 applyFormula(a, b, c, d, e)
 fmt.Println("a is now", a)
}

a is     [1 2 3 4]
a is now [689.1127648209083 786.9429631647291 879.4931076599294 1001.3783018264178]

复制代码
fn main() {
    let mut a: [f32; 5] = [5., 2., 8., 9., 0.5]; // we want it to be mutable
    let b: [f32; 5] = [7., 9., 8., 0.965, 0.98]; 
    let c: [f32; 5] = [0., 0.8, 789456., 123456., 0.0003]; 
    let d: [f32; 5] = [332., 0.1, 8., 9874., 0.3]; 

    const e: f32 = 85.;

    for i in 0..a.len() {
        a[i] = e * (a[i] + b[i] * c[i] + d[i].cos());
    }

    println!("{:?}", a); //Don't have any idea about the output
}

[470.29297, 866.57544, 536830750.0, 10127158.0, 123.7286]

209. Type with automatic deep deallocation

Declare a type t which contains a string s and an integer array n with variable size, and allocate a variable v of type t. Allocate v.s and v.n and set them to the values "Hello, world!" for s and [1,4,9,16,25], respectively. Deallocate v, automatically deallocating v.s and v.n (no memory leaks).

自动深度解除分配的类型

复制代码
package main

func main() {
 f()
}

func f() {
 type t struct {
  s string
  n []int
 }

 v := t{
  s: "Hello, world!",
  n: []int{1, 4, 9, 16, 25},
 }

 // Pretend to use v (otherwise this is a compile error)
 _ = v

 // When f exits, v and all its fields are garbage-collected, recursively
}

After v goes out of scope, v and all its fields will be garbage-collected, recursively


复制代码
struct T {
 s: String,
 n: Vec<usize>,
}

fn main() {
 let v = T {
  s: "Hello, world!".into(),
  n: vec![1,4,9,16,25]
 };
}

When a variable goes out of scope, all member variables are deallocated recursively.

211. Create folder

Create the folder at path on the filesystem

创建文件夹

复制代码
package main

import (
 "fmt"
 "os"
)

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

 err = os.Mkdir(path, os.ModeDir)
 if err != nil {
  panic(err)
 }

 info, err2 := os.Stat(path)
 b = !os.IsNotExist(err2)
 fmt.Println(path, "exists:", b)
 fmt.Println(path, "is a directory:", info.IsDir())
}

foo exists: false
foo exists: true
foo is a directory: true

or

复制代码
package main

import (
 "fmt"
 "os"
)

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

 err = os.Mkdir(path, os.ModeDir)
 if err != nil {
  fmt.Println("Could not create", path, "with os.Mkdir")
 }

 info, err2 := os.Stat(path)
 b = !os.IsNotExist(err2)
 fmt.Println(path, "exists:", b)

 err = os.MkdirAll(path, os.ModeDir)
 if err != nil {
  fmt.Println("Could not create", path, "with os.MkdirAll")
 }

 info, err2 = os.Stat(path)
 b = !os.IsNotExist(err2)
 fmt.Println(path, "exists:", b)
 fmt.Println(path, "is a directory:", info.IsDir())
}

foo/bar exists: false
Could not create foo/bar with os.Mkdir
foo/bar exists: false
foo/bar exists: true
foo/bar is a directory: true

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

fn main() {
    let path = "/tmp/goofy";
    let b: bool = Path::new(path).is_dir();
    println!("{} exists: {}", path, b);

    let r = fs::create_dir(path);
    match r {
        Err(e) => {
            println!("error creating {}: {}", path, e);
            std::process::exit(1);
        }
        Ok(_) => println!("created {}: OK", path),
    }

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

/tmp/goofy exists: false
created /tmp/goofy: OK
/tmp/goofy exists: true

or

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

fn main() {
    let path = "/tmp/friends/goofy";
    let b: bool = Path::new(path).is_dir();
    println!("{} exists: {}", path, b);

    // fs::create_dir can't create parent folders
    let r = fs::create_dir(path);
    match r {
        Err(e) => println!("error creating {}: {}", path, e),
        Ok(_) => println!("created {}: OK", path),
    }

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

    // fs::create_dir_all does create parent folders
    let r = fs::create_dir_all(path);
    match r {
        Err(e) => println!("error creating {}: {}", path, e),
        Ok(_) => println!("created {}: OK", path),
    }

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

/tmp/friends/goofy exists: false
error creating /tmp/friends/goofy: No such file or directory (os error 2)
/tmp/friends/goofy exists: false
created /tmp/friends/goofy: OK
/tmp/friends/goofy exists: true

212. Check if folder exists

Set boolean b to true if path exists on the filesystem and is a directory; false otherwise.

检查文件夹是否存在

复制代码
package main

import (
 "fmt"
 "os"
)

func main() {
 path := "foo"
 info, err := os.Stat(path)
 b := !os.IsNotExist(err) && info.IsDir()
 fmt.Println(path, "is a directory:", b)

 err = os.Mkdir(path, os.ModeDir)
 if err != nil {
  panic(err)
 }

 info, err = os.Stat(path)
 b = !os.IsNotExist(err) && info.IsDir()
 fmt.Println(path, "is a directory:", b)
}

foo is a directory: false
foo is a directory: true

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

fn main() {
    let path = "/etc";
    let b: bool = Path::new(path).is_dir();
    println!("{}: {}", path, b);

    let path = "/goofy";
    let b: bool = Path::new(path).is_dir();
    println!("{}: {}", path, b);
}

/etc: true
/goofy: false

215. Pad string on the left

Prepend extra character c at the beginning of string s to make sure its length is at least m. The length is the number of characters, not the number of bytes.

左侧补齐字符串

复制代码
package main

import (
 "fmt"
 "strings"
 "unicode/utf8"
)

func main() {
 m := 3
 c := "-"
 for _, s := range []string{
  "",
  "a",
  "ab",
  "abc",
  "abcd",
  "é",
 } {
  if n := utf8.RuneCountInString(s); n < m {
   s = strings.Repeat(c, m-n) + s
  }
  fmt.Println(s)
 }
}

---
--a
-ab
abc
abcd
--é

复制代码
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
if let Some(columns_short) = m.checked_sub(s.width()) {
    let padding_width = c
        .width()
        .filter(|n| *n > 0)
        .expect("padding character should be visible");
    // Saturate the columns_short
    let padding_needed = columns_short + padding_width - 1 / padding_width;
    let mut t = String::with_capacity(s.len() + padding_needed);
    t.extend((0..padding_needed).map(|_| c)
    t.push_str(&s);
    s = t;
}

*This uses the Unicode display width to determine the padding needed. This will be appropriate for most uses of monospaced text.

It assumes that m won't combine with other characters to form a grapheme.*

217. Create a Zip archive

Create a zip-file with filename name and add the files listed in list to that zip-file.

创建压缩文件

复制代码
package main

import (
 "archive/zip"
 "bytes"
 "io"
 "io/ioutil"
 "log"
 "os"
)

func main() {
 list := []string{
  "readme.txt",
  "gopher.txt",
  "todo.txt",
 }
 name := "archive.zip"

 err := makeZip(list, name)
 if err != nil {
  log.Fatal(err)
 }
}

func makeZip(list []string, name string) error {
 // Create a buffer to write our archive to.
 buf := new(bytes.Buffer)

 // Create a new zip archive.
 w := zip.NewWriter(buf)

 // Add some files to the archive.
 for _, filename := range list {
  // Open file for reading
  input, err := os.Open(filename)
  if err != nil {
   return err
  }
  // Create ZIP entry for writing
  output, err := w.Create(filename)
  if err != nil {
   return err
  }

  _, err = io.Copy(output, input)
  if err != nil {
   return err
  }
 }

 // Make sure to check the error on Close.
 err := w.Close()
 if err != nil {
  return err
 }

 N := buf.Len()
 err = ioutil.WriteFile(name, buf.Bytes(), 0777)
 if err != nil {
  return err
 }
 log.Println("Written a ZIP file of", N, "bytes")

 return nil
}

func init() {
 // Create some files in the filesystem.
 var files = []struct {
  Name, Body string
 }{
  {"readme.txt", "This archive contains some text files."},
  {"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
  {"todo.txt", "Get animal handling licence.\nWrite more examples."},
 }
 for _, file := range files {
  err := ioutil.WriteFile(file.Name, []byte(file.Body), 0777)
  if err != nil {
   log.Fatal(err)
  }
 }
}

list contains filenames of files existing in the filesystem. In this example, the zip data is buffered in memory before writing to the filesystem.

2009/11/10 23:00:00 Written a ZIP file of 492 bytes


复制代码
use zip::write::FileOptions;
let path = std::path::Path::new(_name);
let file = std::fs::File::create(&path).unwrap();
let mut zip = zip::ZipWriter::new(file); zip.start_file("readme.txt", FileOptions::default())?;                                                          
zip.write_all(b"Hello, World!\n")?;
zip.finish()?;

or

复制代码
use zip::write::FileOptions;
fn zip(_name: &str, _list: Vec<&str>) -> zip::result::ZipResult<()>
{
    let path = std::path::Path::new(_name);
    let file = std::fs::File::create(&path).unwrap();
    let mut zip = zip::ZipWriter::new(file);
    for i in _list.iter() {
        zip.start_file(i as &str, FileOptions::default())?;
    }
    zip.finish()?;
    Ok(())
}

218. List intersection

Create list c containing all unique elements that are contained in both lists a and b. c should not contain any duplicates, even if a and b do. The order of c doesn't matter.

列表的交集

复制代码
package main

import (
 "fmt"
)

type T int

func main() {
 a := []T{4, 5, 6, 7, 8, 9, 10}
 b := []T{1, 3, 9, 5, 7, 9, 7, 7}

 // Convert to sets
 seta := make(map[T]bool, len(a))
 for _, x := range a {
  seta[x] = true
 }
 setb := make(map[T]bool, len(a))
 for _, y := range b {
  setb[y] = true
 }

 // Iterate in one pass
 var c []T
 for x := range seta {
  if setb[x] {
   c = append(c, x)
  }
 }

 fmt.Println(c)
}

[5 7 9]


复制代码
use std::collections::HashSet;

fn main() {
    let a = vec![1, 2, 3, 4];
    let b = vec![2, 4, 6, 8, 2, 2];

    let unique_a = a.iter().collect::<HashSet<_>>();
    let unique_b = b.iter().collect::<HashSet<_>>();
    let c = unique_a.intersection(&unique_b).collect::<Vec<_>>();

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

c: [2, 4]

or

复制代码
use std::collections::HashSet;

fn main() {
    let a = vec![1, 2, 3, 4];
    let b = vec![2, 4, 6, 8, 2, 2];

    let set_a: HashSet<_> = a.into_iter().collect();
    let set_b: HashSet<_> = b.into_iter().collect();
    let c = set_a.intersection(&set_b);

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

c: [2, 4]

219. Replace multiple spaces with single space

Create string t from the value of string s with each sequence of spaces replaced by a single space.

Explain if only the space characters will be replaced, or the other whitespaces as well: tabs, newlines.

用单个空格替换多个空格

复制代码
package main

import (
 "fmt"
 "regexp"
)

// regexp created only once, and then reused
var whitespaces = regexp.MustCompile(`\s+`)

func main() {
 s := `
 one   two
    three
 `

 t := whitespaces.ReplaceAllString(s, " ")

 fmt.Printf("t=%q", t)
}

t=" one two three "


复制代码
use regex::Regex;

fn main() {
    let s = "
 one   two
    three
 ";
    let re = Regex::new(r"\s+").unwrap();
    let t = re.replace_all(s, " ");
    println!("{}", t);
}

one two three

220. Create a tuple value

Create t consisting of 3 values having different types.

Explain if the elements of t are strongly typed or not.

创建元组值a

复制代码
t := []interface{}{
 2.5,
 "hello",
 make(chan int),
}

A slice of empty interface may hold any values (not strongly typed).


复制代码
fn main() {
    let mut t = (2.5, "hello", -1);
    
    t.2 -= 4;
    println!("{:?}", t);
}

(2.5, "hello", -5)

参考资料

1

Rust Vs Go: Which Language Is Better For Developing High-Performance Applications?: https://analyticsindiamag.com/rust-vs-go-which-language-is-better-for-developing-high-performance-applications/

本文由mdnice多平台发布

相关推荐
IT利刃出鞘3 小时前
Spring工具类--ObjectUtils的使用
java·后端·spring
2601_949816683 小时前
Spring boot启动原理及相关组件
数据库·spring boot·后端
GetcharZp9 小时前
告别 jq 噩梦!这款 JSON 神器 fx 让你在终端体验“丝滑”的数据操作
后端
小码哥_常10 小时前
告别臃肿!Elasticsearch平替Manticore登场
后端
苍何11 小时前
万字保姆级教程:Hermes+Kimi K2.6 打造7x24h Agent军团
后端
我叫黑大帅11 小时前
为什么map查找时间复杂度是O(1)?
后端·算法·面试
FreeCultureBoy13 小时前
用 phpbrew 管理 php 环境:从安装到多版本切换
后端·php
FreeCultureBoy14 小时前
用 jenv 管理 Java 环境:从安装 JDK 到多版本切换
后端
IT_陈寒14 小时前
Vite的热更新突然失效,原来是因为这个配置
前端·人工智能·后端
考虑考虑14 小时前
SQL语句中的order by可能造成时间重复
数据库·后端·mysql