• 网络相关和Go语言踩坑


    IP预留部分

    RFC 1918 为私有网络预留出了三个IP 地址块,如下:
    A 类:10.0.0.0~10.255.255.255
    B 类:172.16.0.0~172.31.255.255
    C 类:192.168.0.0~192.168.255.255
    上述三个范围内的地址不会在因特网上被分配,因此可以不必向ISP 或注册中心申请而在公司或企业内部自由使用。

    安装docker后无法联网

    这个直接官网装就好,安装完了还有一个初次使用的教程,看着蛮贴心的,但是笑里藏刀啊!!

    docker会自动加入电脑自启动项,并且装完了docker会出现计算机无法联网的情况,用电脑管家啥的是修不好的,原因出在设置了代理。

    用电脑自带的“设置-网络-网络疑难解答”可以发现提示“远程计算机或设备降不接受连接”。

    解决方法为“Internet选项-连接-局域网设置-取消所有的勾选框(一般是取消代理服务器)”

    docker代理设置

    打开docker客户端,上方的设置(齿轮按钮),RESOURCE-PROXIES,打开Manual proxy configuration,设置http代理socks5://127.0.0.1:10808/(我用的socks协议,如果是v2光线客户端课打开参数设置查看端口)

    什么时候要用代理呢?比如你访问不了gcr.io。

     

    cannot find main module; see 'go help modules'

    vscode打开go文件后报错,完整报错信息为

    The code in the workspace failed to compile (see the error message below).
    If you believe this is a mistake, please file an issue: https://github.com/golang/go/issues/new.
    go [-e -json -compiled=true -test=true -export=false -deps=true -find=false -- ./]: exit status 1: go: cannot find main module; see 'go help modules'
    : packages.Load error

    原因是你使用过go env -w GO111MODULE=on命令让强制使用go.mod,而你的go文件目录中没有。

    解决方法为生成一个mod文件,或者设置GO111MODULE为auto(通过user系统环境变量的方式,否则会提示does not override conflicting OS environment variable)然后重启电脑

    参考https://blog.csdn.net/u011897301/article/details/105758056/

    vscode里面debug Golang的launch.json配置

    {
        // 使用 IntelliSense 了解相关属性。 
        // 悬停以查看现有属性的描述。
        // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
        "version": "0.2.0",
        "configurations": [
            {
                "name": "Golang",
                "type": "go",
                "request": "launch",
                "remotePath": "",
                "port": 5546,
                "host": "127.0.0.1",
                "program": "${fileDirname}",
                "env": {
                    "GOPATH":"c:/gowork/mygo",
                    "GOROOT":"c:/GO",
                },
                "args": [
                    "-config",
                    "config.json"
                ]//这里添加的命令行参数
            }
        ]
    }

      

    GO语言入门

    推荐一个文档build-web-application-with-golang

    https://github.com/wbhs614/build-web-application-with-golang/blob/master/zh/preface.md

    • fmt是format的缩写,fmt包提供了格式化输入输出,你可以理解为c++的iostream,导入的方式又类似于python
    • package main 定义了包名,每个 Go 应用程序都包含一个名为 main 的包。
    • func main() 是程序开始执行的函数,main 函数是每一个可执行程序所必须包含的
    • 注释的方法和javascript完全一致,使用 //单行注释 和 /* 这是注释块 */ 的方式
    • 特殊的含义:当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 protected )。
    • 结束了党争:完美地解决了代码中“左花括号另起一行好还是不另起一行好”的问题,因为你另起一行就会报错或者被误解!!!有一个有趣的题目,可以看一看https://www.v2ex.com/t/562318

     Go 语言的断行规则定义如下:

    • 在 Go 代码中,注释除外,如果一个代码行的最后一个语法词段( token )为下列所示之一,则一个分号将自动插入在此字段后(即行尾):
      • 一个标识符;
      • 一个整数、浮点数、虚部、码点或者字符串字面表示形式;
      • 这几个跳转关键字之一:breakcontinuefallthroughreturn
      • 自增运算符++或者自减运算符--
      • 一个右括号:)]}
    • 为了允许一条复杂语句完全显示在一个代码行中,分号可能被插入在一个右小括号)或者右大括号}之前。
    • switch代码块中开大括号{前的比较表达式可以省略,其默认值为true,可以结合上面的链接中的例子来看
    • GO语言在行结尾像python一样不需要打分号;,会按照上面的断行规则由编译器自动添加。但是如果你想让多句放在同一行,就需要手动打分号;
    • GO语言的变量声明和赋值https://studygolang.com/articles/1275,一般:= 用于函数内变量声明,var ( [换行写多个] )用于全局变量声明
      var name type 比如 var myNumber int = 10
    • 如果你想要交换两个变量的值,则可以简单地使用 a, b = b, a,两个变量的类型必须是相同。
    • 为什么字符串类型的 unsafe.Sizeof() 一直是16呢?
      实际上字符串类型对应一个结构体,该结构体有两个域,第一个域是指向该字符串的指针,第二个域是字符串的长度,每个域占8个字节,但是并不包含指针指向的字符串的内容,这也就是为什么sizeof始终返回的是16。要看字符的个数应该用len("abc")

    • iota:const声明常量中的第一个 iota 等于 0,每增加一行都会自动加 1,第几行使用的iota就等于几;https://www.runoob.com/go/go-constants.html

    • 跟c++一样有++--运算符,存在指针*和引用&,说到底GO就是因为c编译太慢了才写的
    • 函数定义有点特殊,返回类型跟在参数的后面,变量的类型都是在变量后面,可以返回多个值,如func swap(num1, num2 int) (int, int) { /*函数功能*/ } ,需要改变传入变量的值,就需要接收指针*,调用函数的时候传递引用&
      func function_name( [parameter list] ) [return_types] {
         函数体
      }
    • 数组的声明与初始化:其中第二行的[5]可以省略为[...],编译器会根据后面的元素个数自动判断数组大小。访问的方法同c++,但是也有python中冒号:自动补全剩余索引的用法arr[startIndex:],arr[:endIndex]

      var balance [10] float32
      var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    • fmt格式化输出的%x占位符表示十六进制,可以用于输出内存地址等,关于格式化输出占位符的说明https://www.cnblogs.com/qing123/articles/4353353.html
    • Golang中的空指针指向的是nil,对应c++的Null,指针内存地址为0,可以通过p == nil判断是否为空指针
    • Golang中的struct结构体声明是把var变成type,比如type Books struct,在创建变量的时候还是var Book1 Books = {“”,“”}。
    • 当要将结构体对象转换为 JSON 时,对象中的属性首字母必须是大写(public),才能正常转换为 JSON。那这样 JSON 字符串以后就只能是大写了么? 当然不是,可以使用 tag 标记要返回的字段名。
      type Person  struct{
           Name  string   `json:"name"`   //标记json名字为name   
           Age    int     `json:"age"`
           Time int64    `json:"-"`        // 标记忽略该字段
      
      }
    • Golang中的切片也是个神奇的用法,相当于动态数组,跟数组的区别就是创建的时候为空的方括号[ ],拥有上限cap()和实际长度len(),可以被append()和copy()

    关于从数组中生成切片,因为是使用的数组中某个开始元素的指针,所以cap()取决于数组这个开始元素到结束有多少个内存位置,详见https://www.runoob.com/go/go-slice.html#div-comment-39031,而且由于使用的是指针,数组和切片的任何修改都可能互相影响(append只改变自己)。

    关于切片的容量增加,首先是将新元素数量往上取偶数,加到原cap上,如果加了之后大于原cap两倍,那这就是新cap;如果加了还不够原cap的两倍,则如果原cap小于1024,新cap就是2倍原cap;如果原cap大于等于1024,新cap为原cap循环乘以1.25,直到装得下,详见https://www.runoob.com/go/go-slice.html#comment-56326

    • Golang的range关键字用法:range返回的是数组(array)、切片(slice)、通道(channel)或集合(map)的索引(map对应的是key)和元素,其中索引如果用不上,可以被抛弃,比如下面的i换成关键字_。字符串也可以用range,只是出来的是字符(Unicode的值)本身

    for _, num := range nums {
            sum += num
        }

    • Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

    var countryCapitalMap map[string]string /*创建集合 */
        countryCapitalMap = make(map[string]string) /*如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对 */

    • 来到最为特色的一个关键字了:go,通过 go 关键字来开启 goroutine 即实现并发多线程,在使用函数的时候前面加个go。
    • 多个goroutine之间传递数据使用通道chan来进行,使用前需要用make(chan   xxx)关键字申明创建,使用信道传递可以避免主函数提前于子线程结束,关于多线程更多的参考https://www.runoob.com/go/go-concurrent.html
    • defer 语句是Go中一个非常有用的特性,可以将一个方法延迟到包裹该方法的方法返回时执行,在实际应用中,defer语句可以充当其他语言中try…catch…的角色,也可以用来处理关闭文件句柄等收尾操作。详见https://www.jianshu.com/p/79c029c0bd58
    • 字符串分割:下面的例子吧adress字符串按照冒号分为了一个数组
      strings.Split(adress, ":")

     

    golang socketio处理json参数

    gosocketio "github.com/graarh/golang-socketio"
    https://github.com/wbhs614/build-web-application-with-golang/blob/master/zh/07.2.md
    • gosocketio.Dial()返回一个通道c,在其中注册"success"方法,其中返回的数据使用空接口f interface{}接收。
    • 这个时候f里面存储了一个map类型,他们的key是string,值存储在空的interface{}里

      f = map[string]interface{}{
      	"Name": "Wednesday",
      	"Age":  6,
      	"Parents": []interface{}{
      		"Gomez",
      		"Morticia",
      	},
      }

      那么如何来访问这些数据呢?通过断言的方式:

      m := f.(map[string]interface{})

      通过断言之后,你就可以通过如下方式来访问里面的数据了

      for k, v := range m {
      	switch vv := v.(type) {
      	case string:
      		fmt.Println(k, "is string", vv)
      	case int:
      		fmt.Println(k, "is int", vv)
      	case float64:
      		fmt.Println(k,"is float64",vv)
      	case []interface{}:
      		fmt.Println(k, "is an array:")
      		for i, u := range vv {
      			fmt.Println(i, u)
      		}
      	default:
      		fmt.Println(k, "is of a type I don't know how to handle")
      	}
      }

      通过上面的示例可以看到,通过interface{}与type assert的配合,我们就可以解析未知结构的JSON数了。

    • 上面这个是官方提供的解决方案,其实很多时候我们通过类型断言,操作起来不是很方便,目前bitly公司开源了一个叫做simplejson的包,在处理未知结构体的JSON时相当方便

     

    在Golang中将两个或多个[] map [string] interface {}类型合并为一个

    在实际运用中遇到了gosocketio返回的是一个切片的interface

    [map[one:1 two:2] map[three:3 four:4]]

    生成方法见http://www.voidcn.com/article/p-vpszqmnf-bup.html

    对应的解析是使用断言m1 := v.([]interface{})[0]可以取出第一个interface map,需要注意取出后类型还是interface,然后继续断言

    小技巧是在用断言的时候如果类型错误会引导进panic报错,根据报错的内容可以判断此变量为什么类型的数据,这也是我自己摸索出来的,菜的坑,哎。

    		m := v.([]interface{})[0]//取出第一个
    		data := m.(map[string]interface{})//断言取出map类型的数据
    		adress := data["address"].(string)//map里面还是interface类型,所以需要转换string
    		adressArray := strings.Split(adress, ":")//adress为 xx.xx.xx.xx:xxx,需要分割出ip和port
    		fmt.Printf("IP: %s
    ", adressArray[0])
    		fmt.Printf("Port: %s
    ", adressArray[1])
    		fmt.Printf("ID: %s
    ", data["id"].(string))
    		fmt.Printf("Room ID: %s
    ", data["room_id"].(string))
    		fmt.Printf("Name: %s
    ", data["name"].(string))

    在Go文件运行时读取命令行参数以及读写文件

    参考https://www.cnblogs.com/believepd/p/10952528.html,但是更推荐把获取的操作放在init()函数中

    var (
    	config string
    )
    
    func init() {
    	//解析命令行输入,分别为&变量,关键字,默认值,提示词
    	flag.StringVar(&config, "config", "config.json", "json文件路径,默认为同目录的config.json")
    	flag.Parse()
    }
    
    func main() {
    	readJson(config)//读文件
    }
    

    读写文件https://www.cnblogs.com/zengyjun/p/10218088.html

  • 相关阅读:
    [LeetCode] 771. Jewels and Stones
    [LeetCode] 129. Sum Root to Leaf Numbers
    java定时器demo
    Spring Boot与监控管理
    springboot与热部署
    springboot中的web项目不能访问templates中的静态资源
    @Component 和 @Bean 的区别
    springcluoud入门
    Dubbo和Zookerper的关系
    Spring boot配置Dubbo三种方式
  • 原文地址:https://www.cnblogs.com/smileglaze/p/13893794.html
Copyright © 2020-2023  润新知