golang学习笔记——http.Handle和http.HandleFunc的区别与type func巧妙运用

news2024/11/14 20:06:10

文章目录

  • http.Handle和http.HandleFunc的区别
  • http.Handle分析
    • type func巧妙运用
  • http.HandleFunc分析
  • 总结
  • 参考资料

http.Handle和http.HandleFunc的区别

http.Handle和http.HandleFunc的区别体现了Go语言接口的巧妙运用

下面代码启动了一个 http 服务器,监听 8080 端口,并注册路由。实现这两个路由注册的方法有点不同,一个使用 http.Handle,另一个使用 http.HandleFunc ,下面来看看这两个之间的区别;
在这里插入图片描述

http.Handle分析

我们简单看一下http.Handle函数
在这里插入图片描述
这个 Handler 类型是什么呢,其实它就是一个接口,包含一个 ServeHttp() 的方法:

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

在Go语言常规代码中,接口一般是这样用的

// Sayer 接口
type Sayer interface {
    say()
} 

type dog struct {}

type cat struct {} 

// dog实现了Sayer接口
func (d dog) say() {
    fmt.Println("汪汪汪")
}

// cat实现了Sayer接口
func (c cat) say() {
    fmt.Println("喵喵喵")
} 

先写一个接口,再写一个结构体,最后将结构体与方法相关联,也就是这个结构体类型dog实现了接口。

其实type关键字作用是声明类型,这里应该写为dog类型实现Sayer接口,cat类型实现Sayer接口,比较合适。(一个对象只要全部实现了接口中的方法,那么就实现了这个接口。)

我们再看一个例子

package main

import "fmt"

type Sayer interface {
    say()
} 

type dog int

// dog实现了Sayer接口
func (d dog) say() {
    fmt.Println("汪汪汪")
}

func main() {
   var d dog
   d.say()
}

没错,我们把int类型重新定义为一个新的类型,这个类型叫dogdog这个类型也实现了Sayer接口。所以,玩转一个接口一般分为三步:

  • 第一步定义一个接口类型,
  • 第二步定义一个非接口类型
  • 第三步在非接口类型上实现接口。

所以,第二步的代码只要定义一个非接口类型即可。

type func巧妙运用

我们知道,func也是一种类型,那可以试着用func类型实现接口。

type Sayer interface {
    say(str string)
} 

type Dog func(string)

func (f Dog) say(str string) {
	f(str)
}

代码写到IDE上也没有报错,说明这段代码是可行的。代码中的f(str)又是什么意思。f(str)看起来有点像一个名叫f的函数,传入了一个str的参数,当方法被调用时(注意,Go语言中方法与函数的区别),这个函数就行执行,只不过这个函数的类型是Dog类型。等等,有点不对。这个函数就行执行,执行了什么?所以,执行之前一定要有一个Dog类型的实例。可以是一个有名称的函数,也可以是一个匿名函数,

package main

import "fmt"

type Sayer interface {
    say(str string)
} 

type Dog func(string)

func (f Dog) say(str string) {
	f(str)
}

func main() {
	d := Dog(func(str string){
		fmt.Println("转换类型")
	})
	
	d("开始执行")
}

特别要注意的是这段代码中的Dog(func(str string)表示是一个强制转换,把匿名函数转为Dog类型。理解了type func,再看方法二也就不难了。

http.HandleFunc分析

从代码上看函数二比函数一少定义了一个结构体,简洁一些,写起来也方便一些。那为什么函数二比函数一少写了一个结构体? 下面看代码

func HandleFunc(pattern string,
	handler func(ResponseWriter, *Request)) {
	DefaultServeMux.HandleFunc(pattern, handler)
}

通过源码得知HandleFunc是http包下的一个大写字母开头的公开函数,该函数接收两个参数,一个是路由匹配的字符串,另外一个是 func(ResponseWriter, *Request) 类型的函数。

然后继续调用 DefaultServeMux.HandleFunc(pattern, handler)

func (mux *ServeMux) HandleFunc(pattern string,
	handler func(ResponseWriter, *Request)) {
	if handler == nil {
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
}

可以看到,代码中的第6行,HandlerFunc(handler),HandlerFunc可不是一个函数,而是类型转换

Go语言中只有强制类型转换,没有隐式类型转换。下面的语法只能在两个类型之间支持相互转换的时候使用。

  • 强制类型转换的基本语法如下:
    T(表达式)
    
    其中,T表示要转换的类型。表达式包括变量、复杂算子和函数返回值等。

这里是把 handler 转换成了 HandlerFunc 类型,而 HandlerFunc 类型则如下所示:

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}

该类型实现了 Handler 接口(因为该类型有一个ServeHTTP方法),所以其也可以转换成 Handler 类型,接下来调用 mux.Handle(pattern string, handler Handler) 就跟 http.Handle 的流程是一样的了。

	Handler接口   --->	HandlerFunc类型
					  ︿ 		\
					 /	         \
					/	          ﹀
匿名函数   --->   强制转换       HandlerFunc类型的ServeHTTP方法调用HandlerFunc类型的函数      

总结

http.Handle的使用方法和面向对象编程差不多,第一步定义一个接口类型,第二步定义一个非接口类型,第三步在非接口类型上实现接口。

http.HandleFunc使用上简洁一些,但原理比较复杂。先定义一个函数(参数类型,返回值都要和ServeHTTP一样),再将它强转为HandlerFunc类型,HandlerFunc类型有一个方法叫ServeHTTP,这方法会执行一个名叫f的函数,这个函数的类型就是HandlerFunc。因为一个对象只要全部实现了接口中的方法,那么就实现了这个接口。所以,HandlerFunc类型实现了type Handler interface这个接口。所以,我们只要写一个匿名函数,内部就会为我们转为HandlerFunc类型。

参考资料

理解go的function types
golang中 type func() 用法分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1402962.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么使用AI人工智能抠图?不妨试试这样做

在数字时代的浪潮中,人工智能技术如春雨般悄然渗透到各个领域,其中尤以图像处理领域为甚。在这场技术的革新中,AI抠图应运而生,它凭借自动识别和提取图像中目标物体的神奇能力,成为图像处理领域的璀璨新星。通过背景与…

编程和数值计算平台:MATLAB R2023a(Win/Mac)激活版

MATLAB R2023a是一款强大的数值计算和科学编程软件,广泛应用于工程、科学和数学领域。 win版:https://soft.macxf.com/soft/3541.html?idMzE5MTM%3D mac版:https://www.macz.com/mac/9321.html?idOTI2NjQ5Jl8mMjcuMTg2LjkuOTg%3D 以下是MAT…

EtherNet/IP开发:C++开发CIP源代码

① 介绍一下CIP CIP是一种考虑到自动化行业而设计的通用协议。然而,由于其开放性,它可以并且已经应用于更多的领域。CIP网络库包含若干卷: 第1卷介绍了适用于所有网络自适应的CIP的常见方面。本卷包含通用对象库和设备配置文件库&#xff0…

Linux与windows互相传输文件之rzsz命令

文章目录 关于rzsz安装软件使用命令方法一:直接拖拽方法二:直接在终端输入rz 关于rzsz 这个工具用于 windows 机器和远端的 Linux 机器通过 XShell 传输文件 安装完毕之后可以通过拖拽的方式将文件上传过去 首先看一下我们的机器可以使用网络吗&#xff…

Spring Boot 4.0:构建云原生Java应用的前沿工具

目录 前言 Spring Boot简介 Spring Boot 的新特性 1. 支持JDK 17 2. 集成云原生组件 3. 响应式编程支持 4. 更强大的安全性 5. 更简化的配置 Spring Boot 的应用场景 1. 云原生应用开发 2. 响应式应用程序 3. 安全性要求高的应用 4. JDK 17的应用 总结 作…

IS-IS:01 ISIS基本配置

这是实验拓扑,下面是基本配置: R1: sys sysname R1 user-interface console 0 idle-timeout 0 0 int loop 0 ip add 1.1.1.1 24 int g0/0/0 ip add 192.168.12.1 24 qR2: sys sysname R2 user-interface console 0 idle-timeout 0 0 int loop 0 ip add …

网络安全的信息收集方法有哪些?

网络安全攻击中的信息收集是攻击者为了了解目标系统的弱点、配置、环境和潜在的防御措施而进行的活动。以下是一些常见的信息收集手段: 开放网络资源查询: 使用搜索引擎查找关于目标组织的信息,包括新闻稿、社交媒体帖子、官方网站等。通过W…

c语言小游戏之扫雷

目录 一:游戏设计理念及思路 二:初步规划的游戏界面 三:开始扫雷游戏的实现 注:1.创建三个文件,test.c用来测试整个游戏的运行,game.c用来实现扫雷游戏的主体,game.h用来函数声明和包含头文…

使用Rancher管理Kubernetes集群

部署前规划 整个部署包括2个部分,一是管理集群部署,二是k8s集群部署。管理集群功能主要提供web界面方式管理k8s集群。正常情况,管理集群3个节点即可,k8s集群至少3个。本文以3节点管理集群,3节点k8s集群为例 说明部署过…

flink部署模式介绍

在一些应用场景中,对于集群资源分配和占用的方式,可能会有特定的需求。Flink 为各种场景提供了不同的部署模式,主要有以下三种,它们的区别主要在于: 集群的生命周期以及资源的分配方式;应用的 main 方法到…

All the stories begin at installation

Before installation, there are some key points about Conan: “Conan is a dependency and package manager for C and C languages.”“With full binary management, Conan can create and reuse any number of different binaries (for different configurations like a…

实时asr新服务串讲

1.背景及现状 工程方面目前语音相关服务存在大量重复代码,逻辑复杂,文档缺失,并且某些细节设计不合理。基于目前现状,代码业务与功能耦合严重,迭代困难,将来增加新的能力也需要改动音频数据相关代码&#x…

Vue 实例创建流程

✨ 专栏介绍 在当今Web开发领域中,构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架,正是为了满足这些需求而诞生。它采用了MVVM架构模式,并通过数据驱动和组件化的方式,使…

带大家做一个,易上手的家常葱爆牛肉

先准备一块牛肉 划水去冰 然后多清洗几次 尽力洗出血水 准备 大葱: 主要根据牛肉的量来。和我这块牛肉差不多的 三分之二根就够了。 三四个干辣椒 主要看你想让它有多辣 两瓣大蒜 大葱切段 干辣椒就原样就好 大蒜去皮切片 牛肉切片 起锅烧油 油烧热后 下牛肉翻炒 牛肉完全…

RPC框架简介

RPC定义 远程过程调用(Remote Procedure Call)。RPC的目的就是让构建分布式计算(应用)更加简单,在提供强大的调用远程调用的同时不失去简单的本地调用的语义简洁性 RPC整体架构 服务端启动时首先将自己的服务节点信息…

vue生命周期图示

详见:官网介绍

MyBatis 的XML实现方法(JAVA)

数据库表的结构如下: DROP DATABASE IF EXISTS test; CREATE DATABASE test DEFAULT CHARACTER SET utf8mb4; -- 使⽤数据数据 USE test; -- 创建表[⽤⼾表] DROP TABLE IF EXISTS userinfo; CREATE TABLE userinfo ( id INT ( 11 ) NOT NULL AUTO_INCREMENT, user…

【Linux】权限 !

Linux 权限 Liunx Linux 权限1 什么是权限1.1 Linux用户1.2 切换用户 2 权限管理2.1 文件访问者的分类2.2 文件类型和访问权限2.3 文件权限的设置方法chmod 命令chown 命令chgrp 命令umask 命令file 指令 2.4 目录权限粘滞位 3 权限总结 1 什么是权限 关于Linux的权限问题&…

vivado 接口、端口映射

接口 重要&#xff01;接口只能在“fpga”类型的&#xff1c;component&#xff1e;中定义。接口部分提供了<component>上所有可用物理接口的列表。<interfaces>部分包含嵌套在其中的一个或多个<interface>标记。一个接口是通过使用<port_map>标记由多…

OpenGL DIR

Mesa简介-CSDN博客 Mesa, also called Mesa3D and The Mesa 3D Graphics Library, is an open source software implementation of OpenGL, Vulkan, and other graphics API specifications. Mesa translates these specifications to vendor-specific graphics ha…