西维蜀黍

【MySQL】用户和权限管理

MySQL权限

关于MySQL的权限简单的理解就是MySQL允许你做你全力以内的事情,不可以越界。比如只允许你执行select操作,那么你就不能执行update操作。只允许你从某台机器上连接MySQL,那么你就不能从除那台机器以外的其他机器连接MySQL。

那么MySQL的权限是如何实现的呢?这就要说到MySQL的两阶段验证,下面详细介绍:

  • 第一阶段:服务器首先会检查你是否允许连接。因为创建用户的时候会加上主机限制,可以限制成本地、某个IP、某个IP段、以及任何地方等,只允许你从配置的指定地方登陆。
  • 第二阶段:如果你能连接,MySQL会检查你发出的每个请求,看你是否有足够的权限实施它。比如你要更新某个表、或者查询某个表,Mysql会查看你对哪个表或者某个列是否有权限。再比如,你要运行某个存储过程,MySQL会检查你对存储过程是否有执行权限等。
  ...


【MySQL】MySQL安全性设置

  ...


【MySQL】Establishing a Database Connection

  ...


【Golang】Set实现

Interface

type Set interface {
	// Adds an element to the set. Returns whether
	// the item was added.
	Add(i interface{}) bool

	// Returns the number of elements in the set.
	Cardinality() int

	// Removes all elements from the set, leaving
	// the empty set.
	Clear()

	// Returns a clone of the set using the same
	// implementation, duplicating all keys.
	Clone() Set

	// Returns whether the given items
	// are all in the set.
	Contains(i ...interface{}) bool

	// Returns the difference between this set
	// and other. The returned set will contain
	// all elements of this set that are not also
	// elements of other.
	//
	// Note that the argument to Difference
	// must be of the same type as the receiver
	// of the method. Otherwise, Difference will
	// panic.
	Difference(other Set) Set

	// Determines if two sets are equal to each
	// other. If they have the same cardinality
	// and contain the same elements, they are
	// considered equal. The order in which
	// the elements were added is irrelevant.
	//
	// Note that the argument to Equal must be
	// of the same type as the receiver of the
	// method. Otherwise, Equal will panic.
	Equal(other Set) bool

	// Returns a new set containing only the elements
	// that exist only in both sets.
	//
	// Note that the argument to Intersect
	// must be of the same type as the receiver
	// of the method. Otherwise, Intersect will
	// panic.
	Intersect(other Set) Set
	
	...
}	
  ...


【Golang】go-redis 连接Redis

go-redis

client := redis.NewClient(&redis.Options{
	Addr:     "localhost:6379",
	Password: "", // password
	DB:       0,  // use default DB
})

pong, err := client.Ping().Result()
fmt.Println(pong, err)
var id uint64 = 64
rule := &Rule{
	Id: &id,
}
b, err := json.Marshal(rule)
if err != nil {
	panic(err)
}

fmt.Println(client.Set("cache1", b, 0).Result())

a, err := client.Get("cache1").Result()

var item myProto.CompositeLogisticPromotionRule
err = json.Unmarshal([]byte(a), &item)
if err != nil {
	panic(err)
}
fmt.Println(item.Id)
  ...


【Network】通过反向代理实现内网穿透

Background

树莓派通常会(通过LAN 或者 WIFI)连接到一个路由器上,如果我们不方便在路由器上配置端口映射(或者这个路由器之外还有另外的 NAT),当我们不在这个内网时,就无法管理我们的树莓派。

这时候,我们可以考虑使用用于内网穿透的反向代理应用。

如果你有一个拥有公网 IP 的机器,比如云主机、VPS 等。那么最稳定的方式就是在这个机器上自己架设中转节点。

  ...


【Golang】内置函数

当我们想要在 Go 语言中初始化一个结构时,可能会用到两个不同的关键字 — make 和 new。因为它们的功能相似,所以初学者可能会对这两个关键字的作用感到困惑,但是它们两者能够初始化的却有较大的不同。

  • make 的作用是初始化内置的数据结构,包括且仅包括 slice、map 和 Channel
  • new 的作用是根据传入的类型分配一片内存空间,并返回指向这片内存空间的指针

make()

slice := make([]int, 0, 100)
hash := make(map[int]bool, 10)
ch := make(chan int, 5)
  1. slice 是一个包含 data、cap 和 len 的结构体 reflect.SliceHeader;
  2. hash 是一个指向 runtime.hmap 结构体的指针;
  3. ch 是一个指向 runtime.hchan 结构体的指针;
  ...


【Golang】数据类型

类型

序号 类型 描述
1 布尔型(boolean type) 布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。
2 数字类型(numeric type) 整型(integer values) int 和浮点型(floating-point values) float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。
3 字符串类型(string type) 字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
4 派生类型: 包括:(a) 指针类型(Pointer)(b) 数组类型(c) 结构化类型(struct)(d) Channel 类型(e) 函数类型(f) 切片类型(g) 接口类型(interface)(h) Map 类型

布尔型(boolean type)

布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。

数字类型(numeric type)

整型(Integer types)

The predeclared architecture-independent numeric types are:

序号 类型和描述
1 uint8 无符号(unsigned) 8 位整型 (0 到 255)
2 uint16 无符号 16 位整型 (0 到 65535)
3 uint32 无符号 32 位整型 (0 到 4294967295)
4 uint64 无符号 64 位整型 (0 到 18446744073709551615)
5 int8 有符号(signed) 8 位整型 (-128 到 127)
6 int16 有符号 16 位整型 (-32768 到 32767)
7 int32 有符号 32 位整型 (-2147483648 到 2147483647)
8 int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)

There is also a set of predeclared numeric types with implementation-specific sizes:

序号 类型和描述
3 uint 32 或 64 位,由 architecture 决定。如果是32位CPU就是4个字节,如果是64位就是8个字节
4 int 与 uint 一样大小
5 uintptr 无符号整型,用于存放一个指针
uint either 32 or 64 bits
int  same size as uint

Demo

package main

import (
	"fmt"
	"runtime"
	"unsafe"
)

func main() {
	fmt.Println("arch:", runtime.GOARCH)

	var i1 int = 1
	var i2 int8 = 2
	var i3 int16 = 3
	var i4 int32 = 4
	var i5 int64 = 5
	fmt.Println("int:", unsafe.Sizeof(i1))
	fmt.Println("int8:", unsafe.Sizeof(i2))
	fmt.Println("int16:", unsafe.Sizeof(i3))
	fmt.Println("int32:", unsafe.Sizeof(i4))
	fmt.Println("int64:", unsafe.Sizeof(i5))
}

// output:
// arch: amd64
// int: 8
// int8: 1
// int16: 2
// int32: 4
// int64: 8

浮点型(Floating-point Numbers)

序号 类型 描述
1 float32 IEEE-754 32位浮点型数
2 float64 IEEE-754 64位浮点型数
3 complex64 32 位实数(real part)和虚数(imaginary part)
4 complex128 64 位实数和虚数

其他数字类型

以下列出了其他更多的数字类型:

序号 类型和描述
1 byte 类似 uint8
2 rune 类似 int32
  ...


【Golang】循环

For

package main

import "fmt"

func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}

无限循环

如果循环中条件语句永远不为 false 则会进行无限循环,我们可以通过 for 循环语句中只设置一个条件表达式来执行无限循环:

实例

package main

import "fmt"

func main() {
  for true {
    fmt.Printf("这是无限循环。\n");
  }
}

Or

package main

func main() {
	for {
	}
}

For-each range 循环

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:

package main
import "fmt"

func main() {
        strings := []string{"google", "runoob"}
        for i, s := range strings {
                fmt.Println(i, s)
        }


        numbers := [6]int{1, 2, 3, 5}
        for i,x:= range numbers {
                fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
        }  
}

while

package main

import "fmt"

func main() {
	sum := 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)
}
  ...


【Golang】异常处理

异常处理

Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 的这种异常处理方式。

因为Go语言的设计者们认为,将异常处理逻辑与业务逻辑混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。

在Go语言中,通过利用多值返回来返回错误。因此,不要用异常代替错误(在 Go 的世界中,我们只能使用 error,而不是 exception),更不要用是否有抛出异常来改变控制程序执行流程(在 Java、C#中我们往往都是这样做的)。在极个别的情况下,也就是说,遇到真正的异常的情况下(比如除数为0了)。才使用Go中引入的Exception处理:defer, panic, recover。

这几个异常的使用场景可以这么简单描述:Go中可以通过调用 panic() 来抛出一个异常(这意味着你可以在任何地方调用 panic() 来表示一个自定义异常),然后通过 defer 关键字声明一个异常处理函数,最后在这个异常处理函数中通过 recover() 捕获任何之前未被捕获的异常,并进行相应的异常处理。

  ...