Blog

patience is the key in life


  1. 创建map-》分配空间-》赋值

    1
    2
    3
    4
    5
    6
    // 1. 先声明变量,然后开辟空间,最后赋值
    var map1 map[int]string
    map1 = make(map[int]string, 10)
    map1[1] = "php"
    map1[2] = "python"
    map1[3] = "java"
  2. 创建map同时分配空间-》赋值

    1
    2
    3
    4
    5
    // 2. 声明变量的同时分配空间,然后赋值
    map2 := make(map[int]string, 10)
    map2[1] = "Jordan"
    map2[2] = "Kobe"
    map2[3] = "xxx"
  3. 创建map同时分配空间同时赋值

    1
    2
    3
    4
    5
    6
    // 3. 声明变量同时分配空间同时赋值
    map3 := map[int]string{
    1: "Nike",
    2: "Adidas",
    3: "Anta",
    }

    测试1-3结果

  4. 增删改查+函数修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    // map是引用类型,所以形参是引用传递
    func update(cityMap map[string]string) {
    cityMap["Fujian"] = "Fuzhou"
    }
    func main() {

    // 基本操作-CURD
    map1 := make(map[string]string)

    // 1. 增
    fmt.Println("----增----")
    map1["Fujian"] = "Fuzhou"
    map1["Guangdong"] = "Guangzhou"
    map1["Zhejiang"] = "Hangzhou"
    fmt.Println(map1)

    // 2. 删
    fmt.Println("----删----")
    delete(map1, "Zhejiang")
    fmt.Println(map1)

    // 3. 改
    fmt.Println("----改----")
    map1["Fujian"] = "XiaMen"
    fmt.Println(map1)

    // 4. 查
    fmt.Println("----查----")
    for key, value := range map1 {
    fmt.Println("key:", key, "value:", value)
    }

    // 5. 通过函数修改map值
    fmt.Println("----通过引用传递修改map值----")
    update(map1)
    fmt.Println(map1)

    }

    测试结果


  1. 声明变量-》分配空间-》赋值

    1
    2
    3
    4
    5
    6
    7
    // 1. 声明切片,但不赋值
    var slice1 []int // 声明切片
    slice1 = make([]int, 3) // 开辟空间
    slice1[0] = 1 // 赋值
    slice1[1] = 2
    slice1[2] = 3
    fmt.Println(slice1)
  2. 声明变量并分配空间-》赋值

    1
    2
    3
    4
    5
    6
    // 2. 声明切片并分配空间
    slice2 := make([]int, 3) // 声明并分配空间
    slice2[0] = 1 // 赋值
    slice2[1] = 2
    slice2[2] = 3
    fmt.Println(slice2)
  3. 截取

    1
    2
    3
    4
    5
    6
    // 3.截取 [startIndex:endIndex) 左闭右开
    slice3 := slice2[0:2]
    fmt.Println(slice3)
    // slice3指向slice2所在内存空间的起始地址处
    slice3[0] = 100
    fmt.Println("slice2 :", slice2)

    测试结果

  4. 复制 (若没有分配内存空间,则无法进行有效复制)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 4.复制 需要分配内存空间才能有效复制
    var slice4 []int
    fmt.Println("----未分配内存空间的复制----")
    copy(slice4, slice2)
    fmt.Println("slice4 :", slice4)
    fmt.Println("----分配完内存空间的复制----")
    slice4 = make([]int, len(slice2))
    copy(slice4, slice2)
    fmt.Println("slice4 :", slice4)

    测试结果


  1. 不赋值
  2. 全赋值
  3. 部分赋值
  4. 参数传递(值传递、数组长度必须一致

测试1.2.3

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
// 1.静态数组
var arr1 [5]int // 不赋值
var arr2 = [5]int{1, 2, 3, 4, 5} // 全赋值
var arr3 = [10]int{1, 2, 3, 4, 5} // 部分赋值

// 测试
fmt.Println("----静态数组----")
fmt.Println("arr1:", arr1)
fmt.Println("arr2:", arr2)
fmt.Println("arr3:", arr3)
}

结果

测试4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

// 测试静态数组参数传递
func test2(array [5]int) {
array[0] = 100
}

func main() {
// 1.静态数组
var arr1 [5]int // 不赋值
var arr3 = [10]int{1, 2, 3, 4, 5} // 部分赋值

// 测试
fmt.Println("----静态数组----")
fmt.Println("arr1:", arr1)
fmt.Println("arr3:", arr3)

// 测试值传递
test2(arr1)
fmt.Println("----函数调用后----")
fmt.Println("arr1:", arr1)

// 测试数组长度不一致的参数传递
test2(arr3)
}

测试值传递结果

测试数组长度不一致结果


  1. defer的执行顺序(执行到defer关键字时,将该行代码压栈,方法执行结束后,逐个弹栈并执行方法)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 1.defer的执行顺序
    func func1() {
    fmt.Println("func1 ...")
    }
    func func2() {
    fmt.Println("func2 ...")
    }
    func func3() {
    fmt.Println("func3 ...")
    }

    func main() {
    // 测试defer执行顺序
    defer func1()
    defer func2()
    defer func3()
    }

    结果

  2. defer和return谁先谁后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 2. defer和return的先后顺序
    func deferFunc() {
    fmt.Println("deferFunc ...")
    }
    func returnFunc() int {
    fmt.Println("returnFunc ...")
    return 0
    }
    func testDeferAndReturn() int {
    defer deferFunc()
    return returnFunc()
    }

    func main() {
    // 测试defer和return的执行顺序
    testDeferAndReturn()
    }

    结果


  1. 值传递

    1
    2
    3
    4
    5
    6
    7
    // 值传递
    func swap1(a int, b int) {
    var temp int
    temp = a
    a = b
    b = temp
    }
  2. 引用传递

    1
    2
    3
    4
    5
    6
    7
    // 引用传递
    func swap2(pa *int, pb *int) {
    var temp int
    temp = *pa
    *pa = *pb
    *pb = temp
    }
  3. 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    func main() {
    var a int = 10
    var b int = 20

    // swap前
    fmt.Println("----初始值----")
    fmt.Println("a = ", a)
    fmt.Println("b = ", b)

    // 值传递后
    fmt.Println("----值传递后----")
    swap1(a, b)
    fmt.Println("a = ", a)
    fmt.Println("b = ", b)

    // 引用传递后
    fmt.Println("----引用传递后----")
    swap2(&a, &b)
    fmt.Println("a = ", a)
    fmt.Println("b = ", b)
    }

    测试结果


  1. 单个返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 单个函数返回值
    func fun1(a string, b int) int {
    fmt.Println("-----fun1-----")
    fmt.Println("a = ", a)
    fmt.Println("b = ", b)

    c := 100

    return c
    }

    执行结果

  2. 多个返回值(不带形参名称)

    1
    2
    3
    4
    5
    // 多个函数返回值-无形参名称
    func fun2() (string, int) {
    fmt.Println("-----fun2-----")
    return "hello", 100
    }

  3. 多个返回值(带形参名称)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 多个函数返回值-有形参名称
    func fun3() (r1 string, r2 int) {
    fmt.Println("-----fun3-----")
    fmt.Println("r1 = ", r1)
    fmt.Println("r2 = ", r2)

    r1 = "hello world"
    r2 = 100

    return
    }


  1. const

    1
    2
    3
    4
    5
    6
    7
    8
    // const 定义常量
    const length = 100

    const (
    SHANGHAI = 1
    BEIJING = 2
    SHENZHEN = 3
    )
  2. iota

    1
    2
    3
    4
    5
    6
    7
    // iota初始值为0 逐行递增 只能在常量中声明
    const (
    XIAMEN = iota
    QUANZHOU
    ZHANGZHOU
    FUZHOU
    )
  3. 执行结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    func main() {
    fmt.Println("length = ", length)
    fmt.Println("SHANGHAI = ", SHANGHAI)
    fmt.Println("BEIJING = ", BEIJING)
    fmt.Println("SHENZHEN = ", SHENZHEN)
    fmt.Println("XIAMEN = ", XIAMEN)
    fmt.Println("QUANZHOU = ", QUANZHOU)
    fmt.Println("ZHANGZHOU = ", ZHANGZHOU)
    fmt.Println("FUZHOU = ", FUZHOU)
    }


Go的声明变量的方式相比Java简单了很多

  1. 带var 和 变量类型

image.png
image.png
int默认值是0

  1. 带var 但 不带变量类型

image.png
image.png

  1. 不带var 也 不带变量类型

image.png
image.png

  1. 多变量声明

image.png


Go的主函数声明需要在文件头处声明包是main包,这与真实的文件名helloworld.go并不冲突
image.png
一个包下只能有一个主函数
image.png
这样的话这一个包下如果有很多函数,这些函数都得在唯一的一个main函数里头测试吗?
image.png


为什么

实际开发中可能出现远程服务在维护暂时访问不了的情况出现,利用mock模拟调用真实的远程服务可以便于接口的测试、调试、开发

怎么实现

利用动态代理技术生成接口实现类的对象,并在处理器中重写相关的逻辑,返回特定的值

动态代理

根据传入的参数让JVM自动实现静态代理部分的代码,也就是动态生成了接口的实现类

  1. 重写invocationHandler中的invoke方法,可以根据method的返回类型来给出要返回的默认值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 根据方法的返回值类型,生成特定的默认值对象
    Class<?> methodReturnType = method.getReturnType();
    // log.info("mock invoke {}", method.getName());

    return getDefaultObject(methodReturnType);
    }

    private Object getDefaultObject(Class<?> type){
    // 基本类型
    if(type.isPrimitive()){
    if(type == boolean.class){
    return false;
    }
    else if(type == short.class){
    return (short)0;
    }
    else if(type == int.class){
    return 0;
    }
    else if(type == long.class){
    return 0L;
    }
    }
    // 对象类型
    return null;
    }
  2. 然后就可以通过Proxy.newProxyInstance()方法依次传入要实现的类的加载器classLoader、类数组、自定义的处理器

    1
    2
    3
    4
    5
    6
    public static <T> T getMockProxy(Class<T> serviceClass){
    return (T)Proxy.newProxyInstance(
    serviceClass.getClassLoader(),
    new Class[]{serviceClass},
    new MockServiceProxy());
    }
0%