Go的http包详解

Go的http包详解 详细地解剖一下 http 包,看它到底是怎样实现整个过程的。 Go 的 http 有两个核心功能:Conn、ServeMux Conn的goroputine 为了实现高并发和高性能,go使用了goroutine来处理Conn的读写事件,这样每个请求都能保持独立,相互不会阻塞,可以高效的相应网络事件。 go在等待客户端请求中是这样的: c, err := srv.newConn(rw) if err != nil { continue } go c.serve() 可以看到,客户端的每次请求都会创建一个Conn,这个Conn里面保存了该次请求的信息,然后再传递到相应的handler,该handler中便可以读取到相应的header信息,这样保证了每个请求的独立性。 ServeMux的自定义 conn.server内部调用了http包默认的路由器,通过路由器把本次请求的信息传递到了后端的处理函数,那么这个路由器是怎么实现的呢? 它的结构如下: type ServeMux struct{ mu sync.RWMutext // 锁,请求涉及到并发处理,因此需要一个锁机制 m map[string]muxEntry // 路由规则,一个String对应一个mux实体,这里的String就是注册的一个路由表达式 hosts bool // 是否在任意的规则中带有host信息 } 下面看一下muxEntry type muxEntry struct { explicit bool // 是否精确匹配 h Handler // 这个路由表达式对应哪个handler pattern string // 匹配字符串 } 在看一下Handler的定义 type Handler interface { ServeHTTP(ResponseWriter, *Request) // 路由实现器 } Handler是一个接口,但是附中的sayhelloName函数中并没有实现ServeHTTP这个接口,为什么能添加呢?这是因为http包里面还定义了一个类型HandlerFunc,定义的函数sayhelloName就是这个HandlerFunc调用之后的结果,这个类型默认就实现了ServeHTTP这个方法,即我们调用了HandlerFunc(f),强制类型转换f成为HandlerFunc类型,这样f就拥有了ServeHTTP方法。...

February 25, 2021 · 2 min · 李昌

Go语言中值类型与引用类型

1.值类型与引用类型 值类型:int、float、bool和string这些类型都属于值类型,使用这些类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中。当使用等号=将一个变量的值赋给另一个变量时,如 j = i ,实际上是在内存中将 i 的值进行了拷贝。可以通过 &i 获取变量 i 的内存地址 引用类型:特指slice、map、channel这三种预定义类型。引用类型拥有更复杂的存储结构:(1)分配内存 (2)初始化一系列属性等。一个引用类型的变量r1存储的是r1的值所在的内存地址(数字),或内存地址中第一个字所在的位置,这个内存地址被称之为指针,这个指针实际上也被存在另外的某一个字中 2.值类型与引用类型的区别 首先明确,golang中无论是什么类型,传参时都是传递的原值的复制,因此,值类型直接传入函数,任何变动都会反映到原值上,而对于引用类型,其传递的是原值类型的一个复制,因此在函数内的修改,可能会反映到原值中,也可能不会。具体取决引用类型的构造方式及其内部定义。可参考另一篇文章slice和数组的区别 2.1.值类型 //先定义一个数组 var a = [5]int{1, 2, 3, 4, 5} //定义一个函数,将数组中的第一个值设为0 func change(a [5]int){ a[0] = 0 fmt.Println(a) } change(a) fmt.Println(a) 输出: [0 2 3 4 5] [1 2 3 4 5] 可以看到,数组在函数内部被变成{0,1,2,3,4},但当函数结束,还是原来的值没有变。 2.2 引用类型 map的构造函数返回的是一个指针,指向map对象,因此对于map的任何操作都会反映到原map中 // 定义一个map var dit = make(map[string]int) dit["one"] = 1 fmt.Println(dit) // 传参并做改变 func change(dit map[string]int){ dit["two"] = 2 fmt....

February 25, 2021 · 1 min · 李昌

Go语言中的字面量

Go语言中的字面量 Go语言中的字面量 什么是字面量 整型和浮点型的字面值 字符串的字面值 常量的字面值 数组的字面值 Slice的字面值 Map的字面值 结构体的字面值 什么是字面量 在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation)。 简单的说,字面量或者说字面值就是一个变量的值。 整型和浮点型的字面值 var i int = 1 var f float64 = 3.14159 字符串的字面值 字符串值也可以用字符串面值方式编写,只要将一系列字节序列包含在双引号即可: "Hello 世界" `世界` 世界 一个原生的字符串面值形式是 `...` 使用反引号代替双引号。在原生的字符串面值中,没有转义操作;全部的内容都是字面的意思,包含退格和换行,因此一个程序中的原生字符串面值可能跨越多行(译注:在原生字符串面值内部是无法直接写```````字符的,可以用八进制或十六进制转义或+"`"链接字符串常量完成)。唯一的特殊处理是会删除回车以保证在所有平台上的值都是一样的,包括那些把回车也放入文本文件的系统(译注:Windows系统会把回车和换行一起放入文本文件中)。 原生字符串面值用于编写正则表达式会很方便,因为正则表达式往往会包含很多反斜杠。原生字符串面值同时被广泛应用于HTML模板、JSON面值、命令行提示信息以及那些需要扩展到多行的场景。 const GoUsage = `Go is a tool for managing Go source code. Usage: go command [arguments] ...` GoUsage Go is a tool for managing Go source code. Usage: go command [arguments] ....

February 25, 2021 · 1 min · 李昌

Go语言中的错误处理策略

0. 错误处理的编码风格 检查某个子函数是否失败后,我们通常将处理失败的逻辑代码放在处理成功的代码之前。如果某个错误会导致函数返回,那么成功的逻辑代码不应该放在else中,而应直接放在函数体中。 1. 错误传播 函数某个子程序的失败,会变成该函数的失败 resp, err := http.Get(url) if err != nil{ return nill, err } 或是构造新的错误信息返回给调用者 doc, err := html.Parse(resp.Body) resp.Body.Close() if err != nil { return nil, fmt.Errorf("parsing %s as HTML: %v", url,err) } 一般而言,被调函数f(x)会将调用信息和参数信息作为发生错误时的上下文放在错误信息中并返回给调用者,调用者需要添加一些错误信息中不包含的信息。 2. 重试失败的操作 如果错误的发生是偶然的,或由不可预知的问题导致的。此时可重新尝试失败的操作,但是在重试时,要限制重试的时间间隔或重试的时间次数,防止无限制的重试。 func WaitForServer(url string) error { const timeout = 1 * time.Minute deadline := time.Now().Add(timeout) for tries := 0; time.Now().Before(deadline); tries++ { _, err := http.Head(url) if err == nil { return nil // success } log....

February 25, 2021 · 1 min · 李昌

HINT : Add or change are lated_name

HINT: Add or change a related_name 解决方案: 需要在setting中重载AUTH_USER_MODEL AUTH_USER_MODEL = ‘users.UserProfile’ users:你的app UserProfile:model

February 25, 2021 · 1 min · 李昌

http/template

http/template 什么是模板 模板是一种常见的视图,通过它我们可以传递数据以使该视图有意义。可以以任何方式对其进行自定义以获取任何可能的输出。 模板包 Go中的模板附带两个包text/template和html/template。文本包允许我们使用模板插入文本,而HTML模板通过提供安全的HTML代码来帮助我们。 Part of template 1. 模板动作 模板动作是主要的控制流程,数据评估功能。这些动作控制最终输出将如何显示 {{ /* a comment isside template */ }} 2. 控制结构 控制结构确定模板的控制流程,有助于产生结构化的输出,以下是模板中的一些控制结构 if语句 {{ if .condition }} {{ else }} {{ end }} 循环块 {{ range .Items }} {{ end }} 3. 功能 函数也可以在模板内部使用,可以使用管道符|来使用预定义的函数 如何预定义函数 下面的代码创建并分析上面定义的模板templ。注意方法调用链的顺序:template.New先创建并返回一个模板;Funcs方法将daysAgo等自定义函数注册到模板中,并返回模板;最后调用Parse函数分析模板。 report, err := template.New("report").Funcs(template.FuncMap{"daysAgo": daysAgo}).Parse(templ) if err != nil { log.Fatal(err) } 在Go中解析模板 现在,我们来解析一些文本和HTML模板 1. 访问数据 要访问传递的数据,使用点.,如下所示: {{ .data }} 2. 解析文本模板 现在,来解析一个文本模板...

February 25, 2021 · 2 min · 李昌

Importsomedatatoplaywith

%matplotlib inline ======================================= Receiver Operating Characteristic (ROC) Example of Receiver Operating Characteristic (ROC) metric to evaluate classifier output quality. ROC curves typically feature true positive rate on the Y axis, and false positive rate on the X axis. This means that the top left corner of the plot is the “ideal” point - a false positive rate of zero, and a true positive rate of one. This is not very realistic, but it does mean that a larger area under the curve (AUC) is usually better....

February 25, 2021 · 4 min · 李昌

Keras函数式API

Keras函数式API 使用函数式API,你可以直接操作张量,也可以把层当做函数来使用,接收张量并返回张量。 # 简单的实例 import os # **** change the warning level **** os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' from keras.models import Sequential, Model from keras import layers from keras import Input # 使用Sequential模型 seq_model = Sequential() seq_model.add(layers.Dense(32, activation='relu', input_shape=(64,))) seq_model.add(layers.Dense(32, activation='relu')) seq_model.add(layers.Dense(10, activation='softmax')) # 对应的函数式API实现 input_tensor = Input(shape=(64,)) x = layers.Dense(32, activation='relu')(input_tensor) x = layers.Dense(32, activation='softmax')(x) output_tensor = layers.Dense(10, activation='softmax')(x) model = Model(input_tensor, output_tensor) model.summary() Model: "model_2" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_2 (InputLayer) (None, 64) 0 _________________________________________________________________ dense_10 (Dense) (None, 32) 2080 _________________________________________________________________ dense_11 (Dense) (None, 32) 1056 _________________________________________________________________ dense_12 (Dense) (None, 10) 330 ================================================================= Total params: 3,466 Trainable params: 3,466 Non-trainable params: 0 _________________________________________________________________ Keras会在后台检索从input_tensor到output_tensor所包含的每一层,并将这些层组合成一个类图的数据结构,即一个Model。这种方法有效的原因在于,output_tensor是通过对input_tensor进行多次变换得到的。如果你试图利用不相关的输入和输出来构建一个模型,那么会得到RuntimeError...

February 25, 2021 · 2 min · 李昌

Linux下的权限管理

Linux下的权限管理 Linux 系统中为什么需要设定不同的权限,所有用户都直接使用管理员(root)身份不好吗? 由于绝大多数用户使用的是个人计算机,使用者一般都是被信任的人(如家人、朋友等)。在这种情况下,大家都可以使用管理员身份直接登录。但在服务器上就不是这种情况了,往往运行的数据越重要(如游戏数据),价值越高(如电子商城数据、银行数据),则服务器中对权限的设定就要越详细,用户的分级也要越明确。 和 Windows 系统不同,Linux 系统为每个文件都添加了很多的属性,最大的作用就是维护数据的安全。举个简单的例子,在你的 Linux 系统中,和系统服务相关的文件通常只有 root 用户才能读或写,就拿 /etc/shadow 这个文件来说,此文件记录了系统中所有用户的密码数据,非常重要,因此绝不能让任何人读取(否则密码数据会被窃取),只有 root 才可以有读取权限。 此外,如果你有一个软件开发团队,你希望团队中的每个人都可以使用某一些目录下的文件,而非团队的其他人则不予以开放。通过前面章节的学习我们知道,只需要将团队中的所有人加入新的群组,并赋予此群组读写目录的权限,即可实现要求。反之,如果你的目录权限没有做好,就很难防止其他人在你的系统中乱搞。 比如说,本来 root 用户才能做的开关机、ADSL 拨接程序,新增或删除用户等命令,一旦允许任何人拥有这些权限,系统很可能会经常莫名其妙的挂掉。而且,万一 root 用户的密码被其他人获取,他们就可以登录你的系统,从事一些只有 root 用户才能执行的操作,这是绝对不允许发生的。 因此,在服务器上,绝对不是所有的用户都使用 root 身份登录,而要根据不同的工作需要和职位需要,合理分配用户等级和权限等级。 Linux 系统中,文件或目录的权限信息,可以使用 ls 命令查看,例如: [root@localhost ~]# ls -al total 156 drwxr-x---. 4 root root 4096 Sep 8 14:06 . drwxr-xr-x. 23 root root 4096 Sep 8 14:21 .. -rw-------. 1 root root 1474 Sep 4 18:27 anaconda-ks.cfg -rw-------. 1 root root 199 Sep 8 17:14 ....

February 25, 2021 · 18 min · 李昌

Linux后台运行程序

Linux后台运行程序 使用screen screen介绍 Screen是一个控制台应用程序,允许您在一个窗口中使用多个终端会话。该程序在shell会话中运行,并充当其他终端会话的容器和管理器,类似于窗口管理器管理窗口的方式。 在许多情况下,创建多个终端窗口是不可能或不理想的。您可能需要在没有运行X服务器的情况下管理多个控制台会话,您可能需要轻松访问许多远程云服务器,或者您可能需要在处理其他任务时监视正在运行的程序的输出。所有需求都可以通过屏幕的强大功能轻松解决。 安装srceen ubuntu下 sudo apt-get install screen manjaro下 sudo pacman -S screen 基本使用方法 使用screen命令打开一个新的窗口,在其中运行你想运行的脚本。 开始运行后, 按ctrl+ad退出窗口 使用screen -r重新进入窗口 附:重定向 命令 说明 command > file 将输出重定向到 file。 command < file 将输入重定向到 file。 command » file 将输出以追加的方式重定向到 file。 n > file 将文件描述符为 n 的文件重定向到 file。 n » file 将文件描述符为 n 的文件以追加的方式重定向到 file。 n >& m 将输出文件 m 和 n 合并。 n <& m 将输入文件 m 和 n 合并。 « tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 Edited by Li Chang

February 25, 2021 · 1 min · 李昌