Giter Club home page Giter Club logo

dushaoshuai.github.io's Introduction

dushaoshuai.github.io's People

Watchers

 avatar  avatar

dushaoshuai.github.io's Issues

MySQL: The JSON Data Type

参考文档

使用 MySQL JSON 数据类型的好处

相比存储 JSON 格式的字符串,使用 MySQL JSON 数据类型有两个好处:

  • 自动校验格式
  • 快速读取文档元素

JSON Merge Patch 格式

具体参考 rfc7396 JSON Merge Patch

主要作用是使用一个 JSON Merge Patch 格式的文档来修改服务器上的一个 JSON 文档

具体使用方法,见 JSON_MERGE_PATCH()JSON_MERGE_PRESERVE() 两个修改 JSON 文档的函数

JSON 文档存储空间

参考

JSON 默认值

#6

索引

todo

JSON 值的部分更新

在 MySQL 8.0 中,满足下列条件,优化器可以执行 JSON 的部分、原地更新:

  • 使用函数 JSON_SET()JSON_REPLACE()、和 JSON_REMOVE() 更新,而不是直接赋值
  • 输入列和目标列必须是同一列
  • 不向原对象或数组中添加新元素
  • 新的 JSON 值不能比该列刚插入时占用的空间大

todo 部分更新和 binlog

JSON 格式

JSON 值写为字符串。在需要 JSON 值的上下文中,MySQL 会解析字符串,如果不是合法的 JSON 值,会产生错误。

k8s concepts

概念 解释
集群(Cluster) 集群是一组被 kubernetes 统一管理和调度的节点。集群中一部分节点作为 Master 节点,负责集群状态的管理和协调,另一部分作为 Node 节点,负责执行具体的任务,实现用户服务的启停等功能。
节点(Node) 一个物理主机或者虚拟机(VM)。可以运行多个 Pod。
Pod 是 k8s 中的最小调度单元,和一个节点绑定,直到结束或者删除。Pod 相当于逻辑上的主机,如同一个物理主机上运行着若干个应用,若干个容器运行在一个 Pod 里,共享网络和存储资源,被一起放置(co-located)和调度(co-scheduled)。每个 Pod 都拥有唯一的 IP 地址。
Deployment Deployment 是一组 Pod 的抽象。通过 Deployment 控制器保障用户指定数量的容器副本正常运行,并且实现了滚动更新等高级功能。当需要更新业务版本时,Deployment 会按照指定策略杀死旧版本 Pod 并启动新版本 Pod。
StatefulSet StatefulSet 是一组 Pod 的抽象,主要用于有状态应用的管理。StatefulSet 生成的 Pod 名称是固定且有序的,确保每个 Pod 独一无二的身份标识。
DaemonSet DaemonSet 是一组 Pod 的抽象,确保每个节点上运行一个 Pod。当集群中有新加入的节点时,k8s 会自动帮助我们在新节点上运行一个 Pod。一般用于日志采集,节点监控等场景。
Job Job 创建一个 Pod 并且保障 Pod 的正常退出。如果 Pod 运行过程中出现了错误,Job 控制器可以帮助我们创建新的 Pod,执行 Pod 执行成功或者达到指定重试次数。
Service Service 是一组 Pod 访问配置的抽象。Service 通过在主机上配置一定的网络规则,帮助我们通过一个固定的 IP 以轮询的负载均衡策略访问一组 Pod。
命名空间(Namespace) k8s 通过命名空间来实现资源的虚拟化隔离。将一组相关联的资源放到同一个命名空间内。
标签(Label) Label 是一组键值对,每一个资源对象都会拥有此字段。k8s 中使用 label 对资源进行标记,根据 label 对资源进行分类和筛选。
ConfigMap ConfigMap 用于存放业务的配置信息。使用 k-v 方式存储,帮助我们将配置数据和应用程序代码分开。
Secret Secret 用于存放业务的敏感配置信息。使用 k-v 方式存储,主要用于存放密码和证书等敏感信息。
TBD TBD

Linux: 下载与校验文件

使用 curl 下载文件

curl -LO https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz

curl -LO https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz.sha256
  • -L : follow redirects
  • -O : write output to a local file in the current working directory

使用 sha256sum 校验文件

$ ls
cni-plugins-linux-amd64-v1.1.1.tgz  cni-plugins-linux-amd64-v1.1.1.tgz.sha256

$ cat cni-plugins-linux-amd64-v1.1.1.tgz.sha256
b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5  cni-plugins-linux-amd64-v1.1.1.tgz

$ sha256sum --check cni-plugins-linux-amd64-v1.1.1.tgz.sha256
cni-plugins-linux-amd64-v1.1.1.tgz: OK
  • --check : read checksums from the FILEs and check them
  • When checking, the input should be a former output of this program. The default mode is to print a line with: checksum, a space, a character indicating input mode ('*' for binary, ' ' for text or where binary is insignificant), and name for each FILE.

Go :: remove elements from slice

slice = append(slice[:remove_start_index], slice[remove_end_index + 1:]...)
  • 保持原来元素的相对顺序
  • 得到的切片的长度就是我们想要的长度,不会包含多余的元素
  • 将切片后面的元素整体前移,效率不高

Go: 使用 interface literal 来检查接口类型变量的动态类型是否实现了某个方法

interface literal 的写法

interface {
    ... method set ...
}

使用 Type assertions

// iface 是一个接口类型的变量
if foo, ok := iface.(interface { ... method set ... }); ok {
    ... use methods ...
}

使用 Type switches

// iface 是一个接口类型的变量
switch x := iface.(type) {
case interface{ ... method set ... }:
    ... use methods ...
case interface{ ... method set ... }:
    ... use methods ...
default:
    ... do something ...
}

这种写法的一些参考

MySQL: Pattern Matching

两种匹配模式

MySQL 提供两种模式匹配:标准 SQL 模式匹配(standard SQL pattern matching)基于扩展的正则表达式的模式匹配(pattern matching based on extended regular expressions)

标准 SQL 模式匹配

  • _ 匹配单个字符
  • % 匹配任意个字符(包括 0 个)
  • 默认大小写不敏感
  • 使用 LIKE 或者 NOT LIKE 比较操作符

例如,匹配以 b 开头的列 SELECT * FROM table_name WHERE column_name LIKE 'b%'

基于扩展的正则表达式的模式匹配

正则表达式语法见 Regular Expression Syntax

使用 REGEXP_LIKE() 函数或者 REGEXP 操作符或者 RLIKE 操作符。

See also

Pattern Matching
Regular Expressions

Go: type T value calls methods with receiver *T

type T value calls methods with receiver *T

type T struct {
	v int
}

func (t *T) setValue(v int) {
	t.v = v
}

func (t *T) getValue() int {
	return t.v
}

func Example_type_T_value_calls_methods_with_receiver_a_pointer_to_T() {
	var t T
	t.setValue(10)
	fmt.Println(t.getValue())

	// Output:
	// 10
}

按照 https://go.dev/ref/spec#Method_sets 的说法,类型 T 是没有方法的,类型 *T 有两个方法 setValue 和 getValue,这里 t 的类型为 T,但却可以调用 receiver 为 *T 的两个方法 setValue 和 getValue,应该是编译器做了工作,调用方法时取了 t 的指针。

See also

Method sets
Method sets.. Some confusion around type T values calling methods with receivers of type *T

ArchLinux Installation On A Tablet PC

ArchLinux Installation On A Tablet PC

Rotate The Screen

ref

echo 1 > /sys/class/graphics/fbcon/rotate_all
echo 2 > /sys/class/graphics/fbcon/rotate_all
echo 3 > /sys/class/graphics/fbcon/rotate_all
echo 4 > /sys/class/graphics/fbcon/rotate_all

Set A Bigger Console Font

ref ref

setfont /usr/share/kbd/consolefonts/iso01-12x22.psfu.gz

Get Arch Linux Mirrorlist Directly From The Website

ref

curl -o /etc/pacman.d/mirrorlist https://archlinux.org/mirrorlist/all/

Install Driver For Sound Cards

ref

JSON 格式

参考

介绍

JSON 是一种轻量的、语言独立的数据交换格式,用于结构化数据的序列化。

JSON 可以表示 6 种数据类型:

4 种 primitive 类型

  • string
  • number
  • boolean
  • null

2 种结构化类型

  • object
  • array

Value

value 可以是 stringnumberbooleannullobject 或者 array

string

string 是由 Unicode 字符组成的序列,用 " 引用,用 \ 转义。例如:

"This is an example JSON string."
"the_first_line\nthe_second_line"

字符使用单个字符组成的 string 表示,例如,字符 a 表示为:

"a"

number

number 可以表示整数,也可以表示浮点数。例如:

-10
10
5.6
5E10
-11e20
11.45e-13
11.45e23

boolean

boolean 值有 truefalse,必须小写。例如:

true

null

null 表示不存在,必须小写。例如:

null

Object

object 是 name/value 对的无序集合。name 是 stringobject{ 开始,以 } 结束。name 和 value 用 : 分隔,name/value 对之间用 , 分隔。例如:

{ }
{
  "name": "value"
}
{
  "key1": 10,
  "key2": "value2",
  "name3": { },
  "chars": ["a", "b", "c", "d"]
}

Array

array 是 value 的有序序列,value 的类型不必相同。以 [ 开始,以 ] 结束,value 之间用 , 分隔。例如:

[ ]
[1, "x", false, null, {"x": 0, "y": 1.1}]

kubernetes: Creating a cluster with kubeadm

机器要求和配置

  • 一个装有 Linux 系统的机器
  • 内存最好是 2 GB 往上,少了也可以凑活吧
  • CPU 最少 2 个核心,不然 kubeadm init 会报错
    • 使用 --ignore-preflight-errors=NumCPU flags,kubeadm 就只会发出警告了
  • 集群的所有机器之间有网络链接
  • 所有节点的主机名,MAC 地址,product_uuid 都各不相同
    • MAC 地址:ip link
    • product_uuid:sudo cat /sys/class/dmi/id/product_uuid
  • 多个网卡
    • 原文链接
    • 这部分还没弄明白,等以后弄明白了再补
  • 端口和防火墙:k8s 和某些插件需要打开某些端口才能工作,如果碰到问题,这里也是个问题排查方向
  • 关闭交换分区,kubelet 才能正确工作
    • lsblk 查看交换分区
    • sudo swapoff /dev/xxx

容器运行时

Installing a container runtime
Container Runtimes

安装 kubeadmkubeletkubectl

kubeadmkubeletkubectl 不能随意升级,见 Upgrading kubeadm clusters

Manjaro

Skip package from being upgraded

Ubuntu

Kubernetes镜像Installing kubeadm, kubelet and kubectl

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - 
sudo cat <<EOF > /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl # pin version

cgroup driver

容器运行时和 kubelet 需要配置相同的 cgroup driver。

kubeadm 配置

#28 (comment)

创建集群

sudo kubeadm init --ignore-preflight-errors=NumCPU --config=~/.kube/kubeadm_config.yaml

按照 kubeadm 的输出继续操作:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

现在 kubectl 可以和 api server 对话了,使用 kubectl 为集群安装 pod 网络:

# https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#install
$ kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
serviceaccount/weave-net created
clusterrole.rbac.authorization.k8s.io/weave-net created
clusterrolebinding.rbac.authorization.k8s.io/weave-net created
role.rbac.authorization.k8s.io/weave-net created
rolebinding.rbac.authorization.k8s.io/weave-net created
daemonset.apps/weave-net created

这样控制平面就起来了,可以给集群添加更多节点了:

sudo kubeadm join a.b.c.e:6443 --token abcdef.0123456789abcdef \           
        --discovery-token-ca-cert-hash sha256:bdffe9db95bb85b742a8e68d5f9d3fb8e4a0e7204bbea75398054ca56eeb93d2
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

See also

Kubernetes on Arch Linux
kubeadm init
Installing kubeadm
Container Runtimes
Creating a cluster with kubeadm

时间单位

Name 中文名 Length
second 1 s
millisecond 毫秒 10-3 s
microsecond 微妙 10-6 s
nanosecond 纳秒 10-9 s

变量名缩写

  • source -> src
  • destination -> dst
  • options -> opts
  • message -> msg
  • parameter -> param
  • parameters -> params
  • controller -> ctrl
  • context -> ctx
  • arguments -> args
  • compatibility -> compat
  • server -> srv

  • foo
  • bar
  • baz
  • qux
  • quux
  • fred
  • thud

数据库范式(Database Normalization)

零范式(zero normal form)

零范式是未经过范式化的数据库设计。范式化的目标是:

  • 消除数据冗余
  • 易于修改数据,并且避免修改数据时造成数据异常
  • 易于实行引用完整性约束
  • 使用易于理解的结构模拟数据表示的真实情况

第一范式(1st normal form)

  • 没有重复的组
  • 所有的关键属性被定义,并且每一个属性都不可再被分为更小的属性
  • 所有的属性都依赖于主键

第二范式(2st normal form)

  • 满足第一范式
  • 不存在部分依赖,部分依赖是说一个属性仅依赖主键的一部分

    如果一个属性仅依赖主键的一部分,那个意味着这个主键由最少两个字段组成;如果已满足第一范式且主键仅包含一个字段,那么就自动满足了第二范式。

第三范式(3st normal form)

  • 满足第二范式
  • 不存在传递依赖,传递依赖是说一个非主键属性通过另一个非主键属性而依赖于主键

参见

Database Normalization

gRPC: Error handling: Richer error model

gRPC 的错误处理用起来不是很方便。一个 RPC 返回的错误,有时是不能展示给用户的,有时又需要展示给用户,区分起来太麻烦了。可以考虑给 Status 额外添加 error details

package status_test

import (
	"fmt"

	"google.golang.org/genproto/googleapis/rpc/errdetails"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

func ExampleWithDetail() {
	s := status.New(codes.ResourceExhausted, "a per-user quota has been exhausted")

	var err error
	s, err = s.WithDetails(
		&errdetails.LocalizedMessage{
			Locale:  "zh-CN",
			Message: "您已领取,下次再来吧",
		},
		&errdetails.Help{
			Links: []*errdetails.Help_Link{
				{
					Description: "gPRC - Richer error model",
					Url:         "https://grpc.io/docs/guides/error/#richer-error-model",
				},
				{
					Description: "googleapis - Error Model",
					Url:         "https://cloud.google.com/apis/design/errors#error_model",
				},
				{
					Description: "googleapis - google.rpc.Status",
					Url:         "https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto",
				},
				{
					Description: "googleapis - google.rpc.error_details",
					Url:         "https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto",
				},
				{
					Description: "google.golang.org/grpc/status",
					Url:         "https://pkg.go.dev/google.golang.org/[email protected]/status",
				},
				{
					Description: "google.golang.org/genproto/googleapis/rpc/errdetails",
					Url:         "https://pkg.go.dev/google.golang.org/genproto/googleapis/rpc/errdetails",
				},
			},
		},
	)
	if err != nil {
		panic(err)
	}

        // return error
        // s.Err() returns an error

	for _, detail := range s.Details() {
		switch detail := detail.(type) {
		case *errdetails.LocalizedMessage:
			fmt.Println(detail.GetLocale(), detail.GetMessage())
		case *errdetails.Help:
			for _, link := range detail.GetLinks() {
				fmt.Println(link.GetDescription())
				fmt.Println(link.GetUrl())
			}
		}
	}

	// Output:
	// zh-CN 您已领取,下次再来吧
	// gPRC - Richer error model
	// https://grpc.io/docs/guides/error/#richer-error-model
	// googleapis - Error Model
	// https://cloud.google.com/apis/design/errors#error_model
	// googleapis - google.rpc.Status
	// https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto
	// googleapis - google.rpc.error_details
	// https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto
	// google.golang.org/grpc/status
	// https://pkg.go.dev/google.golang.org/[email protected]/status
	// google.golang.org/genproto/googleapis/rpc/errdetails
	// https://pkg.go.dev/google.golang.org/genproto/googleapis/rpc/errdetails
}

Network :: 一些术语

Acronym Full Form Index
ARP Address Resolution Protocol(地址解析协议) p305
ARQ Automatic repeat request(自动重传请求), also automatic repeat query p144
CDMA Code Division Multiple Access(码分多址) p295
CMTS Cable Modem Terminatin System(电缆调制调节器) p301
CRC Cyclic Redundancy Check(循环冗余检测) p291
CSMA Carrier Sense Multiple Access(载波侦听多路访问) p295 p298
CSMA/CD CSMA with Collision Detection(具有碰撞检测的 CSMA) p298
EDC Error- Detection and- Correction(差错检测和纠正) p288
FDM (频分多路复用) p294
FEC Forward Error Correction(前向纠错) p290
HDLC high-level data link control(高级数据链路控制) p292
HFC Hybrid Fiber Coaxial cable(混合光纤同轴电缆) p285
MAC Medium Access Control(媒体访问控制) p287
MTU 最大传输单元 p308
NIC Network Interface Card(网络接口卡), also network adapter(网络适配器) p287
PPP Point-to-Point Protocol(点对点协议) p285 p292
SDN Software-Defined Networking(软件定义网络) p198 p202
TDM (时分多路复用) p294

Raspberry Pi :: 使用 Raspberry Pi Imager 安装 Ubuntu Server 22.04.1 LTS 时遇到的问题

使用 Raspberry Pi Imager 安装 Ubuntu Server 22.04.1 LTS 时,已经做了如下配置:

image

但是使用 sudo nmap -sn 192.168.0.0/24 扫描局域网时,仍未找到树莓派的 IP,一开始还以为自己配置有问题,后来在 Ubuntu 官网上找到了原因

原来 Raspberry Pi Imager 并未正确配置网络,需要手动在 SD 卡上非启动分区上的 /etc/netplan/ 文件夹下新建 50-cloud-init.yaml 文件:

wifis:
  wlan0:
    dhcp4: true
    optional: true
    access-points:
      "home network":
        password: "123456789"

See also

Install Ubuntu on a Raspberry Pi
How to install Ubuntu Server on your Raspberry Pi

time zones

IANA Time Zone database
Wikipedia - Time zone
Wikipedia - Lists of time zones
go package - time.Location
Get Current System Time Zone in Linux
go package - tzdata

localtime

/etc/localtime configures the system-wide timezone. It's a symlink pointing to the actual binary timezone data file in /usr/share/zoneinfo/.

$ ls -l /etc/localtime 
lrwxrwxrwx 1 root root 33 Nov 17 06:18 /etc/localtime -> /usr/share/zoneinfo/Asia/Shanghai

See man 5 localtime for more information.

/etc/timezone stores the timezone of the system in plain text format.

$ cat /etc/timezone 
Asia/Shanghai

timedatectl show timezone of the system.

$ timedatectl 
               Local time: Mon 2022-11-21 14:51:29 CST
           Universal time: Mon 2022-11-21 06:51:29 UTC
                 RTC time: Mon 2022-11-21 06:51:29
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

See man timedatectl for more information.

C 数据类型

基本数据类型

type storage (bytes) format specifier (base 10, 8, 16) constant suffix
short 2 %hd %ho %hx
unsigned short 2 %hu
int 4 %d %o %x
unsigned 4 %u
long 8 %ld %lo %lx l (lowercase L) or L
unsigned long 8 %lu ul, LU ...
long long 8 %lld %llo %llx ll or LL
unsigned long long 8 %llu ull, LLu ...

进制

base constant prefix example
8 0 020
10 16
16 0x or 0X 0x10 or 0X10
// bases.c -- prints 16 in decimal, octal, and hex

#include <stdio.h>

int main(void) {
    int x = 16;

    printf("dec = %d; octal = %o; hex = %x\n", x, x, x);
    printf("dec = %d; octal = %#o; hex = %#x\n", x, x, x);
    printf("dec = %d; octal = %#o; hex = %#X\n", x, x, x);

    return 0;
}

// Output:
// dec = 16; octal = 20; hex = 10
// dec = 16; octal = 020; hex = 0x10
// dec = 16; octal = 020; hex = 0X10

MySQL :: Copy Table

1

CREATE TABLE `tb` SELECT * FROM `ta`;

OR

-- https://dev.mysql.com/doc/refman/8.0/en/create-table-select.html#:~:text=%2D%2D%2B-,mysql%3E,-CREATE%20TABLE%20tt1
CREATE TABLE `tb` TABLE `ta`;

2

13.2.6.1 INSERT ... SELECT Statement

CREATE TABLE `tb` LIKE `ta`;
INSERT INTO `tb` SELECT * FROM `ta`; -- Or beginning with MySQL 8.0.19: INSERT INTO `tb` TABLE `ta`; 

Linux: XDG user directories

# ~/.config/user-dirs.dirs
XDG_DESKTOP_DIR="$HOME/Desktop"
XDG_DOCUMENTS_DIR="$HOME/Documents"
XDG_DOWNLOAD_DIR="$HOME/Downloads"
XDG_MUSIC_DIR="$HOME/Music"
XDG_PICTURES_DIR="$HOME/Pictures"
XDG_PUBLICSHARE_DIR="$HOME/Public"
XDG_TEMPLATES_DIR="$HOME/Templates"
XDG_VIDEOS_DIR="$HOME/Videos"

在家目录下生成默认的目录:

$ xdg-user-dirs-update
$ ls
Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos

参考

  1. https://wiki.archlinux.org/title/XDG_user_directories
  2. Go implementation of the XDG Base Directory Specification and XDG user directories

Go :: 格式化浮点数,保留 n 位小数

round to nearest

func RoundPrecision(x float64, precision int) float64 {
	ratio := math.Pow10(precision)
	return math.Round(x*ratio) / ratio
}

round up

func RoundUpPrecision(x float64, precision int) float64 {
	ratio := math.Pow10(precision)
	return math.Ceil(x*ratio) / ratio
}

round down

func RoundDownPrecision(x float64, precision int) float64 {
	ratio := math.Pow10(precision)
	return math.Floor(x*ratio) / ratio
}

MySQL :: JSON Default Value

从 MySQL 8.0.13 开始

原文链接
The BLOB, TEXT, GEOMETRY, and JSON data types can be assigned a default value only if the value is written as an expression, even if the expression value is a literal.

CREATE TABLE jtable (
    jcol JSON DEFAULT (JSON_ARRAY())
);

MySQL 8.0.13 之前

原文链接
The BLOB, TEXT, GEOMETRY, and JSON data types cannot be assigned a default value.

原文链接
Prior to MySQL 8.0.13, a JSON column cannot have a non-NULL default value.

参考

Go: 使用 append() 函数得到一个切片

例如,json.Marshal() 函数中:

buf := append([]byte(nil), e.Bytes()...)

再比如,append() 的注释中:

// As a special case, it is legal to append a string to a byte slice, like this:
// slice = append([]byte("hello "), "world"...)

i18n

What is i18n

tools

golang.org/x/text

text is a repository of text-related packages related to internationalization (i18n) and localization (l10n), such as character encodings, text transformations, and locale-specific text handling.

There is a 30 minute video, recorded on 2017-11-30, on the "State of golang.org/x/text" at https://www.youtube.com/watch?v=uYrDrMEGu58

See also

State of golang.org/x/text
The Go Blog - Language and Locale Matching in Go
Plural Rules
Fluent
JavaScript APIs -> i18n
Tags for Identifying Languages
Picking the Right Language Identifier

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.