西维蜀黍

【Golang】Embedding

Embedding Types Within A Struct

A field declared with a type but no explicit field name is called an embedded field.

// Golang program to illustrate the
// concept of inheritance
package main

import (
	"fmt"
)

type Base struct {
	b int
}

func (base *Base) Describe() string {
	return fmt.Sprintf("base %d belongs to us", base.b)
}

type Container struct { // Container is the embedding struct
	Base // Base is the embedded field
	c    string
}

func main() {
	co := Container{}
	co.b = 1
	co.c = "string"

	// Read the fields within embedded fields
	fmt.Printf("co.b: %v - %v\n", co.b, &co.b)
	fmt.Printf("co.Base.b: %v - %v \n", co.Base.b, &co.Base.b)

	// Call the methods of embedded fields
	fmt.Println(co.Describe())
	fmt.Println(co.Base.Describe())
}
  ...


【Golang】源码 - sync - RWMutex

Source Code

A RWMutex is a reader/writer mutual exclusion lock. The lock can be held by an arbitrary number of readers or a single writer. The zero value for a RWMutex is an unlocked mutex.

A RWMutex must not be copied after first use.

If a goroutine holds a RWMutex for reading and another goroutine might call Lock, no goroutine should expect to be able to acquire a read lock until the initial read lock is released. In particular, this prohibits recursive read locking. This is to ensure that the lock eventually becomes available; a blocked Lock call excludes new readers from acquiring the lock.

type RWMutex struct {
	w           Mutex  // held if there are pending writers
	writerSem   uint32 // semaphore for writers to wait for completing readers
  // 这个 semaphore 在作用是:当ongoing reader 完成了,waiting writer可以被通知到,并且解除blocked,以进行writing
  // 调用 runtime_Semrelease(&rw.writerSem) 可以unblock blocked writer (by wakeup it via semaphore),这时候调用了 runtime_SemacquireMutex(&rw.writerSem) 的地方就不会继续被blocked了
  // 调用 runtime_SemacquireMutex(&rw.writerSem) 的地方会被 blocked,直到 runtime_Semrelease(&rw.writerSem) 被调用
  
	readerSem   uint32 // semaphore for readers to wait for completing writers
  // 这个 semaphore 在作用是:当ongoing writing 完成了,waiting reader可以被通知到,并且解除blocked,以进行reading
  // 调用 runtime_Semrelease(&rw.readerSem) 可以 Unblock blocked readers (by wakeup them via semaphore),这时候调用了 runtime_SemacquireMutex(&rw.readerSem) 的地方就不会继续被blocked了
  // 调用 runtime_SemacquireMutex(&rw.readerSem) 的地方会被 block,直到 runtime_Semrelease(&rw.readerSem) 被调用
	readerCount int32  // number of pending readers
  // if readerCount < 0, means a writing is ongoing (thus all readers have to wait, until the writing is done)
  // if readerCount == 0, means no ongoing writing and no onging reading
  // if readerCount > 0, mean has onging reading, but no ongoing writing
  
	readerWait  int32  // number of departing readers
}

这意味着:

  • 当有writer进来时,
    • 如果这时候没有ongoing reader,writer就直接write
    • 如果这时候有ongoing reader,writer就一直等待(被阻塞在runtime_SemacquireMutex(&rw.writerSem),直到
  • 当有reader进来时,
    • 如果这时候没有ongoing writer,reader就直接read
    • 如果这时候有ongoing writer,reader一直等待(被阻塞在untime_SemacquireMutex(&rw.readerSem)),直到writer完成(writer完成后,会调用runtime_Semrelease(&rw.readerSem)来通知所有reader)
  ...


【Golang】源码 - Channel 实现

Channel 在运行时的内部表示是 runtime.hchan,该结构体中包含了用于保护成员变量的互斥锁,从某种程度上说,Channel 是一个用于同步和通信的有锁队列,使用互斥锁解决程序中可能存在的线程竞争问题是很常见的,我们能很容易地实现有锁队列。

  ...


【Golang】使用 - sync.Mutex

This concept is called mutual exclusion, and the conventional name for the data structure that provides it is mutex.

type Mutex

A Mutex is a mutual exclusion lock(排它锁). The zero value for a Mutex is an unlocked mutex.

A Mutex must not be copied after first use.

type Mutex struct {
    // contains filtered or unexported fields
}
  ...


【Golang】Panic and Recover

  ...


【Golang】Exit Code

os.Exit()

Use os.Exit to immediately exit with a given status.

package main

import (
    "fmt"
    "os"
)

func main() {
    defer fmt.Println("!") // never called

    os.Exit(3)
}
  • Conventionally, code zero indicates success, non-zero an error
  • defers will not be run when using os.Exit, so this fmt.Println will never be called.
  • For portability, the status code should be in the range [0, 125].
  ...


【Golang】使用 - context

Background

Many people who have worked with Go, would have encountered it’s context library. Most use context with downstream operations, like making an HTTP call, or fetching data from a database, or while performing async operations with go-routines. It’s most common use is to pass down common data which can be used by all downstream operations. However, a lesser known, but highly useful feature of context is it’s ability to cancel, or halt an operation mid-way.

This post will explain how we can make use of the context libraries cancellation features, and go through some patterns and best practices of using cancellation to make your application faster and more robust.

  ...


【Python】SimpleHTTPServer

Python2

$ python -m SimpleHTTPServer
# or
$ python2 -m SimpleHTTPServer

Python3

$ python3 -m http.server
  ...


【IoT】大陆以外使用石头拖扫机器人T7S Plus

  ...


【IoT】获取米家设备 token

获取access token

[Better] XIAOMI CLOUD TOKENS EXTRACTOR

Manual run in python

$ git clone https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor.git

$ virtualenv Xiaomi-cloud-tokens-extractor -p python2.7

$ cd Xiaomi-cloud-tokens-extractor

$ source bin/activate

Install dependencies:

$ pip3 install pycryptodome pybase64 requests

Download and run script:

$ python3 token_extractor.py
  ...