101. Load from HTTP GET request into a string
Make an HTTP request with method GET to URL u, then store the body of the response in string s.
发起http请求
package main import ( "fmt" "io/ioutil" "net" "net/http" ) func main() { u := "http://" + localhost + "/hello?name=Inigo+Montoya" res, err := http.Get(u) check(err) buffer, err := ioutil.ReadAll(res.Body) res.Body.Close() check(err) s := string(buffer) fmt.Println("GET response:", res.StatusCode, s) } const localhost = "127.0.0.1:3000" func init() { http.HandleFunc("/hello", myHandler) startServer() } func myHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello %s", r.FormValue("name")) } func startServer() { listener, err := net.Listen("tcp", localhost) check(err) go http.Serve(listener, nil) } func check(err error) { if err != nil { panic(err) } }
res has type *http.Response. buffer has type []byte. It is idiomatic and strongly recommended to check errors at each step.
extern crate reqwest; use reqwest::Client; let client = Client::new(); let s = client.get(u).send().and_then(|res| res.text())?;
or
[dependencies] ureq = "1.0" let s = ureq::get(u).call().into_string()?;
or
[dependencies] error-chain = "0.12.4" reqwest = { version = "0.11.2", features = ["blocking"] } use error_chain::error_chain; use std::io::Read; let mut response = reqwest::blocking::get(u)?; let mut s = String::new(); response.read_to_string(&mut s)?;
102. Load from HTTP GET request into a file
Make an HTTP request with method GET to URL u, then store the body of the response in file result.txt. Try to save the data as it arrives if possible, without having all its content in memory at once.
发起http请求
package main import ( "fmt" "io" "io/ioutil" "net" "net/http" "os" ) func main() { err := saveGetResponse() check(err) err = readFile() check(err) fmt.Println("Done.") } func saveGetResponse() error { u := "http://" + localhost + "/hello?name=Inigo+Montoya" fmt.Println("Making GET request") resp, err := http.Get(u) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return fmt.Errorf("Status: %v", resp.Status) } fmt.Println("Saving data to file") out, err := os.Create("/tmp/result.txt") if err != nil { return err } defer out.Close() _, err = io.Copy(out, resp.Body) if err != nil { return err } return nil } func readFile() error { fmt.Println("Reading file") buffer, err := ioutil.ReadFile("/tmp/result.txt") if err != nil { return err } fmt.Printf("Saved data is %q\n", string(buffer)) return nil } const localhost = "127.0.0.1:3000" func init() { http.HandleFunc("/hello", myHandler) startServer() } func myHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello %s", r.FormValue("name")) } func startServer() { listener, err := net.Listen("tcp", localhost) check(err) go http.Serve(listener, nil) } func check(err error) { if err != nil { panic(err) } }
resp has type http.Response. It is idiomatic and strongly recommended to check errors at each step, except for the calls to Close.
Making GET request Saving data to file Reading file Saved data is "Hello Inigo Montoya" Done.
extern crate reqwest; use reqwest::Client; use std::fs::File; let client = Client::new(); match client.get(&u).send() { Ok(res) => { let file = File::create("result.txt")?; ::std::io::copy(res, file)?; }, Err(e) => eprintln!("failed to send request: {}", e), };
105. Current executable name
Assign to string s the name of the currently executing program (but not its full path).
当前可执行文件名称
将当前正在执行的程序的名称分配给字符串s(但不是它的完整路径)。
package main import ( "fmt" "os" "path/filepath" ) func main() { var s string path := os.Args[0] s = filepath.Base(path) fmt.Println(s) }
fn get_exec_name() -> Option<String> { std::env::current_exe() .ok() .and_then(|pb| pb.file_name().map(|s| s.to_os_string())) .and_then(|s| s.into_string().ok()) } fn main() -> () { let s = get_exec_name().unwrap(); println!("{}", s); }
or
fn main() { let s = std::env::current_exe() .expect("Can't get the exec path") .file_name() .expect("Can't get the exec name") .to_string_lossy() .into_owned(); println!("{}", s); }
106. Get program working directory
Assign to string dir the path of the working directory. (This is not necessarily the folder containing the executable itself)
获取程序的工作路径
package main import ( "fmt" "os" ) func main() { dir, err := os.Getwd() fmt.Println(dir, err) }
use std::env; fn main() { let dir = env::current_dir().unwrap(); println!("{:?}", dir); }
107. Get folder containing current program
Assign to string dir the path of the folder containing the currently running executable. (This is not necessarily the working directory, though.)
获取包含当前程序的文件夹
package main import ( "fmt" "os" "path/filepath" ) func main() { var dir string programPath := os.Args[0] absolutePath, err := filepath.Abs(programPath) if err != nil { panic(err) } dir = filepath.Dir(absolutePath) fmt.Println(dir) }
let dir = std::env::current_exe()? .canonicalize() .expect("the current exe should exist") .parent() .expect("the current exe should be a file") .to_string_lossy() .to_owned();
Rust doesn't represent paths as Strings, so we need to convert the Path returned from Path::parent. This code chooses to do this lossily, replacing characters it doesn't recognize with �
109. Number of bytes of a type
Set n to the number of bytes of a variable t (of type T).
获取某个类型的字节数
package main import ( "fmt" "reflect" ) func main() { var t T tType := reflect.TypeOf(t) n := tType.Size() fmt.Println("A", tType, "object is", n, "bytes.") } type Person struct { FirstName string Age int } // T is a type alias, to stick to the idiom statement. // T has the same memory footprint per value as Person. type T Person
// T has (8 + 4) == 12 bytes of data struct T(f64, i32); fn main() { let n = ::std::mem::size_of::<T>(); println!("{} bytes", n); // T has size 16, which is "the offset in bytes between successive elements in an array with item type T" }
110. Check if string is blank
Set boolean blank to true if string s is empty, or null, or contains only whitespace ; false otherwise.
检查字符串是否空白
package main import ( "fmt" "strings" ) func main() { for _, s := range []string{ "", "a", " ", "\t \n", "_", } { blank := strings.TrimSpace(s) == "" if blank { fmt.Printf("%q is blank\n", s) } else { fmt.Printf("%q is not blank\n", s) } } }
"" is blank "a" is not blank " " is blank "\t \n" is blank "_" is not blank
fn main() { let list = vec!["", " ", " ", "\t", "\n", "a", " b "]; for s in list { let blank = s.trim().is_empty(); if blank { println!("{:?}\tis blank", s) } else { println!("{:?}\tis not blank", s) } } }
"" is blank " " is blank " " is blank "\t" is blank "\n" is blank "a" is not blank " b " is not blank