Result and Option in short

🔔 Prelude: When writing Rust programs, Result and Option are data structures we can hardly avoid. I believe that rather than understanding their underlying mechanisms, we should first quickly figure out how to handle them. Gift Wrapping Actually, we don’t need to think of Option<T> and Result<T,E> as too complicated: Option contains the data we want, where the data type is T. However, there might be no data inside (None). But regardless, as long as what we care about is wrapped, it will be an Option. Result also contains the data we want, but it comes with another “restless” additional item E (Error). In fact, combinations of Result and Option are very common, such as Result<Option<T>, E>. Result provides a powerful and unified specification for Rust’s error handling. So, how do we open the gift box… The moment of unwrapping gifts is always exciting. ...

2026-09-10

Vim in (not so) short

🔔 Prelude: Yes, You can always type :h to see help, for example, :h windows Vim in not so short Preliminaries When vim is not available, you can temporarily use cat or nano as alternatives When using a new IDE, you should first learn or configure: save copy / paste duplicate line delete word / delete line line movement navigate forward / back undo / redo page navigation (page down, page up, center to middle, etc.) indent / unindent multi-cursor search / content search input commands (Ctrl + P in VSCode, double Shift in IntelliJ, : in vim…) completion, suggestion, parameter hint, hover hint go to / peek definition, type, declaration, reference, implementation rename symbol / refactor (if available) AI controlling: toggle chat box, trigger inline chat… tabs / windows management Use the :help command to query anything you don’t understand :set option? can view current settings Windows and Tabs Buffer: Can be understood as a temporary file. Even if this file is edited, it doesn’t mean it’s written to the actual file. We can observe buffers through windows and manage them through tabs. ...

2026-09-10

Golang in short

🔔 Prelude: No need for digging a big hole, just use it. Golang in short Go is A modern high-level programming language that resembles C Open-source, compiled, statically typed, and memory-safe Go has Simple yet powerful package management (pulls directly from GitHub) Built-in concurrency primitives Garbage collection (GC) Lightning-fast compilation Minimal syntax Cross-platform compilation Go doesn’t have Classes and inheritance Function overloading Implicit type conversions I use Go to Say goodbye to Java’s verbose syntax Build web services and microservices Handle high-concurrency scenarios Go is perfect for Web services and RESTful APIs Microservices architecture Network programming and distributed systems Go might not be ideal for GUI desktop applications Kernel development Machine learning (Python has a stronger ecosystem) Installing Go Using OS package managers Linux: apt, yum, snap macOS: brew Windows: choco, scoop, etc. Download official precompiled binaries Already compiled, ready to use Set up path and links manually Verify with go version Hello World // This is a comment /* This is a multiline comment */ package main // This is the main package // No semicolons at line endings import ( "fmt" "math" ) // Importing other packages const myConstant int = 0 // Constants need explicit initialization func main() { fmt.Println("helloworld") // Package names -> lowercase // Lowercase in package -> myConstant -> package-private // Capitalized -> Println() -> exported (public) } Types bool string int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr // Has pointers but no pointer arithmetic byte // alias for uint8 rune // alias for int32 // Represents a Unicode code point // From ancient Nordic "rune" float32 float64 complex64 complex128 // Zero value for reference types is nil // Type assertion t, ok := variable.(int) // Returns two values, ok indicates success // Panics if ok is not captured and type is wrong // Type conversion var myInt int32 = 42 myAnotherInt := int64(myInt) // Type conversion // No direct conversion between bool and int // Generally, single characters and numbers can convert // Otherwise, only conversions within same type family Variables and Functions var hi bool = true // Variables outside functions must have explicit types func myFunc(x, y int) (int, int) { innerHi := "hi" // Inside functions, use := for type inference const hiConst = "hi again" // Constants cannot use := return x + 1, y + 1 } func MapFilter[T any, R comparable]( slice []T, mapper func(T) R, predicate func(R) bool, ) func(options ...int) (filtered []R, count int, err error) { // Returns a function return func(options ...int) (filtered []R, count int, err error) { // Implementation return } } // A complete function signature example // Note the second func starts parameters // The last func starts return type -> returns a function // T is generic, R is constraint, but they're essentially the same thing func(x int) int { return x * 2 } // Anonymous function definition Arrays, Slices, and Maps // Arrays - fixed length var arr [5]int = [5]int{1, 2, 3, 4, 5} arr2 := [...]int{1, 2, 3} // Compiler infers length // Slices - dynamic length var slice []int = []int{1, 2, 3} slice2 := make([]int, 5) // Length 5 slice3 := make([]int, 5, 10) // Length 5, capacity 10 // Maps var m map[string]int = map[string]int{"one": 1, "two": 2} m2 := make(map[string]int) m2["key"] = 42 // Check if key exists value, exists := m["key"] if exists { fmt.Println(value) } Control Flow // Only for loops exist // All parts of for loop are optional for i := 0; i < 10; i++ { // Loop body } // Infinite loop for { // Equivalent to while(true) } // Condition loop i := 0 for i < 10 { i++ } for i, v := range expression {} // Iterate over iterables // Similar to Python's for..in // Directly provides index and value // No enumerate function needed // Use _, v to ignore index // if statement if v := 5; v < 6 { // Can assign in condition // Condition body } // switch statement switch x := 5; x { // x is optional case 1: fmt.Println("one") case 2, 3, 4: // Multiple values fmt.Println("two, three or four") default: fmt.Println("other") } // Type switch switch v := x.(type) { case int: fmt.Printf("int: %d\n", v) case string: fmt.Printf("string: %s\n", v) default: fmt.Printf("unknown type\n") } Defer and Channels // defer - deferred execution (stack structure, LIFO) defer fmt.Println(1) defer fmt.Println(2) defer fmt.Println(3) panic("!") // Output order: 3 2 1 panic // defer provides stack-based deferred execution // panic triggers deferred functions // channel - channels (queue structure, FIFO) func channelExample() { myChan := make(chan int, 2) // Buffer size 2 myChan <- 10 // 10 goes in myChan <- 20 // then 20 goes in took := <-myChan // took is 10 fmt.Println(<-myChan) // 20 } func blockingChannel() { ch := make(chan int) // Unbuffered channel // ch <- 1 // Will block! Need another goroutine to receive // Correct approach go func() { ch <- 1 }() fmt.Println(<-ch) } // Channels provide a queue-like or pipe-like structure // FIFO Pointers // Go has pointers // Useful when referencing large data // Go's design philosophy is very close to C-family languages // Fun fact: When passing pointers to functions, both C and Go copy the pointer // All parameters are pass-by-value in both languages // But C++ has completely different reference passing mechanism func main() { var myPtr *int // var anotherPtr uintptr // uintptr is integer type, not pointer i := 42 myPtr = &i // Take address fmt.Println(*myPtr) // Dereference, outputs 42 *myPtr = 43 // Modify through pointer fmt.Println(i) // Outputs 43 // No pointer arithmetic } Format Verbs Verb Description Example Output %v (value) Default format Printf("%v", people) {zhangsan} %+v Adds field names for structs Printf("%+v", people) {Name:zhangsan} %#v Go syntax representation Printf("%#v", people) main.Human{Name:“zhangsan”} %T (type) Type in Go syntax Printf("%T", people) main.Human %% Percent sign Printf("%%") % %t (true) true or false Printf("%t", true) true %b (binary) Binary representation Printf("%b", 5) 101 %c (char) Unicode character Printf("%c", 0x4E2D) 中 %d (decimal) Decimal Printf("%d", 0x12) 18 %o (octal) Octal Printf("%o", 10) 12 %q (quote) Single-quoted character literal Printf("%q", 0x4E2D) ‘中’ %x Hexadecimal, lowercase Printf("%x", 13) d %X Hexadecimal, uppercase Printf("%X", 13) D %U (unicode) Unicode format: U+1234 Printf("%U", 0x4E2D) U+4E2D %b Binary exponent scientific notation Printf("%b", 10.5) 5835037194198p-49 %e Scientific notation Printf("%e", 10.2) 1.020000e+01 %E Scientific notation Printf("%E", 10.2) 1.020000E+01 %f (float) Decimal point, no exponent Printf("%f", 10.2) 10.200000 %g Compact format (%e or %f) Printf("%g", 10.20) 10.2 %G Compact format (%E or %f) Printf("%G", 10.20) 10.2 %s (string) String (string or []byte) Printf("%s", []byte(“Go”)) Go %q Double-quoted string Printf("%q", “Go”) “Go” %x Hex, lowercase, two chars per byte Printf("%x", “golang”) 676f6c616e67 %X Hex, uppercase, two chars per byte Printf("%X", “golang”) 676F6C616E67 %p (pointer) Hexadecimal with 0x prefix Printf("%p", &people) 0x4f57f0 + Always print sign; ASCII-only for %+q Printf("%+q", “中文”) “\u4e2d\u6587” - Pad with spaces on right (left-align) # Alternate format: 0 prefix for octal (%#o), 0x for hex (%#x), etc. Printf("%#U", ‘中’) U+4E2D ‘中’ ’ ' Space for elided sign; spaces between bytes for hex 0 Pad with zeros; moves padding after sign for numbers Reference: ...

2026-09-10

Basic Makefile

🔔 Prelude: I often noticed Makefile files in the root directory when browsing open-source projects on GitHub. For a long time, I thought it was some kind of sophisticated “magic tool”. So during my spare time at my internship, I decided to learn some basic syntax… only to discover that it’s actually like a “recipe” for compilation - to get a target file (the dish), you need some dependencies (ingredients) and commands (cooking instructions). Anyway, at least now I can understand it (mostly). ...

2026-09-10

JVM in short

What is the JVM? Java programs need the JVM to run. Like .NET Framework. Stands for Java Virtual Machine. Java can run on multiple platforms because JVMs are implemented for different systems. So, Java programs can run on any platform that has a JVM (Though JVM may be different). It executes bytecode, which is translated from Java code. Oh, and Kotlin code can also be compiled into bytecode. What are JRE, JDK, and JAR? JRE (Java Runtime Environment) – It’s what Java needs to run, includes the JVM. JDK (Java Development Kit) – The toolkit for Java developers (You need it to do developing things), and it includes the JRE. It also contains the javac compiler, which turns your code into bytecode. JAR (Java ARchive) – A zip file specifically for Java programs. If everything’s set up correctly, you can run it directly. What is the JVM made of? Class Loader Subsystem – Finds your classes. Runtime Data Area – Contains the native method stack, Java method stack, method area, PC Registers, and heap. Native Method Stack – For calling code in other languages (mainly C++). Java Method Stack – For storing Java function call stacks. PC Registers – Tells the interpreter where to go next. Fact: It’s the only area that won’t throw an OutOfMemoryError. Method Area – Holds class-related info. It’s shared between threads. Heap – Just the heap, shared between threads. Anything not explicitly mentioned is thread-private. Execution Engine – Interpreter, JIT (Just-In-Time compiler), and GC (Garbage Collector). Native Method Library. Class Loader Subsystem? MyClass.java -> Loading (find the class) -> Linking -> Verify, Prepare, Resolve -> Initialization. Verify – Did you write your class correctly? Prepare – Allocates memory for static variables and sets them to default. Resolve – Turns symbolic references (names) into direct references (addresses). Loading: Class Loaders Everything’s an object in Java, even the classes themselves are loaded by class loader objects. ...

2026-09-10

Two Ways to Reverse a Singly Linked List

0. Structure of a Singly Linked List class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next // 1 -> 2 -> 3 -> 4 -> 5 -> NULL 1. Move pointers def reverseList(head: ListNode) -> ListNode: prev = None curr = head while curr: temp = curr.next # Save next node curr.next = prev # Reverse the pointer prev = curr # Move prev forward curr = temp # Move curr forward return prev # New head of the reversed list 0: 1 -> None 2 -> 3 -> 4 -> 5 -> NULL 1: 2 -> 1 -> None 3 -> 4 -> 5 -> NULL ...

2026-09-10

Rust Notes 4

Range Rather than using C style loop, in Rust, we use ..= to indicate a range: for i in 1..=5 { println!("{}",i); } Output: 1 2 3 4 5 Sequences are only allowed for numeric or character types because they can be consecutive. for i in 'a'..='z' { println!("{}",i); } Char Use '' . "" is for the string fn main() { let c = 'z'; let z = 'ℤ'; let cat= '😻'; } Accept Unicode, occupy 4 bytes. ...

2026-09-10

Rust Notes 3

🔔 Prelude: In the end, all data types in Rust come from these primitive types. Basic types Every value in Rust has a specific data type In general, these can be divided into two categories: scalar types and compound types Scalar types include: Numbers: Signed integers (i8, i16, i32, i64, isize), unsigned integers (u8, u16, u32, u64, usize), floating-point numbers (f32, f64) The isize and usize types depend on the architecture of the computer the program is running on: if the CPU is 32-bit, these types are 32-bit; similarly, if the CPU is 64-bit, they are Rust’s default integer type is i32 Can overflow, and Rust does not check for this by default. If you encounter incorrect values, make sure to check the type of your numbers. Strings: String literals and string slices Booleans: true and false Characters: Representing a single Unicode character, stored as 4 bytes Unit type: Represented by (), with its only value also being () Be Careful with floats See this example: ...

2026-09-10

Rust Notes 2

Syntax of Rust Don’t worry, this will be very easy at the beginning. (Really?) Function goes first Similar to C and C++, there must be a main function as the entry point of the program. Use fn to declare a function, so concise. Use () for receiving parameters, and {} for the actual logic inside the function. Remember to use ; to end a statement. As I said, it’s similar to C and C++. Example: fn main() -> { println!("Hello, world!"); // "ln" means print with a new line after the content // What is "!"? Well, it means this function is actually a macro // For now, let's just use it as is // You don't need to learn everything to start using Rust. Heart. } A complete structure of function head in Rust should be: ...

2026-09-10

Rust Notes 1

About these notes These Rust notes are just a collection of my learning records. Since I’m a beginner in Rust, these notes are more like quick references or supplements, rather than a comprehensive Rust tutorial. No matter what, I hope you can still find parts that are useful to you. Why rust? Rust’s advantages include memory safety, high performance, and high productivity. To me, Rust appears to be one of the best implementations of C++. If you don’t get into deeper topics and only use prepared libraries, Rust’s syntax is simple and clear. Its built-in compiler cautions are also quite informative, which significantly decreases the amount of thinking required on developers. ...

2026-09-10