go ip过滤_Go语言实现IP段范围校验示例

本文介绍了如何使用Go语言来实现IP段范围的校验,包括点分十进制范围区分的问题和转换整型进行排查的方法。示例代码展示了从IP字符串到整数的转换,以及如何判断IP是否在指定的IP段范围内。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

近期做了一个需求,是检测某个 IP 是否在若干 IP 段内,做固定地点 IP 筛查,满足特定业务需求。

解决方案

PLAN A 点分十进制范围区分

简单来讲,就是将 IPv4 原有的四段,分别对比 IP 地址,查看每一段是否在 IP 段范围内,可以用于段控制在每一个特定段 0 ~ 255 内筛选,例如:

192.123.1.0 ~ 192.123.156.255

这样的比较规范的特定段可以实现简单的筛选,但是问题来了,不规则的连续 IP 段怎么排除? 如下:

IP段:192.168.1.0 ~ 192.172.3.255

IP: 192.160.0.255

这样就会出现问题,可以看到按照简单的分段对比,很明显校验不通过,但是这个 IP 还是存在在 IP 段中,方案只能针对统一分段下规则的IP段才可以区分。

PLAN B 转整型对别

IP 地址可以转换为整数,可以将 IP 范围化整为 整数范围进行排查。

这种方式只需要将授为范围内的地址转换为整数,就可以将 IP 排查在外了。

代码

以下是示例代码:

package main

import (

"fmt"

"strconv"

"strings"

)

func main() {

ipVerifyList := "192.168.1.0-192.172.3.255"

ip := "192.170.223.1"

ipSlice := strings.Split(ipVerifyList, `-`)

if len(ipSlice) < 0 {

return

}

if ip2Int(ip) >= ip2Int(ipSlice[0]) && ip2Int(ip) <= ip2Int(ipSlice[1]) {

fmt.Println("ip in iplist")

return

}

fmt.Println("ip not in iplist")

}

func ip2Int(ip string) int64 {

if len(ip) == 0 {

return 0

}

bits := strings.Split(ip, ".")

if len(bits) < 4 {

return 0

}

b0 := string2Int(bits[0])

b1 := string2Int(bits[1])

b2 := string2Int(bits[2])

b3 := string2Int(bits[3])

var sum int64

sum += int64(b0) << 24

sum += int64(b1) << 16

sum += int64(b2) << 8

sum += int64(b3)

return sum

}

func string2Int(in string) (out int) {

out, _ = strconv.Atoi(in)

return

}

到此这篇关于Go语言实现IP段范围校验示例的文章就介绍到这了,更多相关Go IP段范围校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

<think>嗯,用户想知道在go-zero框架中关于Redis键生成及获取值的代码含义,特别是涉及fmt.Sprintf生成redisKey的部分。首先,我需要回忆一下go-zero的相关文档和代码结构。 用户提供的代码示例中,redisKey是通过fmt.Sprintf格式化的,使用了constant.MEMBER_PV_PREFIX这个常量作为前缀,结合req.Code参数。这可能是一种常见的键命名方式,用来确保键的唯一性和可读性。然后使用SismemberCtx方法检查某个成员是否存在集合中。 接下来,需要解释这代码的作用,包括键的生成逻辑和Get方法的调用。可能涉及到Redis的数据结构,比如集合(Set),以及Sismember命令的作用。另外,要注意到错误处理部分,比如日志记录和返回自定义错误,这符合go-zero的错误处理规范。 用户可能还想了解为何使用特定的键格式,比如避免键冲突,或者遵循项目中的命名约定。此外,代码中的SismemberCtx方法属于go-zero封装的Redis操作,需要说明其底层实现和优势,比如连接池管理和超时控制。 还要考虑到用户可能的疑问,比如如何选择键的命名方式,或者如何处理缓存击穿等问题。这时候可以引用站内提到的缓存击穿防护方法,比如使用SharedCalls或者进程内缓存,如collection.Cache。同时,提到Redis锁和布隆过滤器可能的相关内容,但需要紧扣当前问题,避免偏离。 需要确保回答结构清晰,分点解释键生成、Get操作、错误处理,以及相关的最佳实践。最后生成的问题要围绕键命名规范、缓存击穿防护、错误处理和集合操作展开,帮助用户深入理解。</think>### go-zero 框架 Redis 键生成与 Get 方法解析 #### 1. **Redis 键生成逻辑** 在 go-zero 中,Redis 键的生成通常通过格式化字符串实现,例如: ```go redisKey := fmt.Sprintf(constant.MEMBER_PV_PREFIX, req.Code) ``` - **`constant.MEMBER_PV_PREFIX`**:是预定义的键名前缀模板,例如 `"member:pv:%s"`,用于统一管理键名格式[^1]。 - **`req.Code`**:动态参数,用于填充模板中的占位符 `%s`,生成唯一的 Redis 键,如 `member:pv:123`。 - **作用**:通过格式化确保键名的唯一性、可读性和可维护性,避免键名冲突。 #### 2. **Get 方法操作(以 `SismemberCtx` 为例)** ```go flag, err := l.svcCtx.RedisCache.SismemberCtx(l.ctx, redisKey, memberBaseInfo.Openid) ``` - **`SismemberCtx`**:判断成员 `memberBaseInfo.Openid` 是否存在于 Redis 集合 `redisKey` 中,返回布尔值 `flag`。 - **底层实现**: - 调用 Redis 原生命令 `SISMEMBER`,时间复杂度为 $O(1)$。 - 自动管理连接池和超时控制,通过 `l.ctx` 支持链路上下文传递[^2]。 - **应用场景**:常用于验证用户权限、去重校验等。 #### 3. **错误处理规范** ```go if err != nil { logx.WithContext(l.ctx).Errorf(err.Error()) return nil, xerr.NewEnsumError(xerr.REDIS_SEARCH_ERROR) } ``` - **日志记录**:使用 `logx.WithContext` 关联请求上下文,便于追踪问题。 - **错误封装**:返回自定义错误码 `xerr.REDIS_SEARCH_ERROR`,统一错误处理逻辑。 #### 4. **最佳实践** - **键命名规范**:推荐使用 `业务:子模块:唯一标识` 格式(如 `member:pv:123`)[^1]。 - **缓存击穿防护**:可结合 `collection.Cache` 进程内缓存或 `NewSharedCalls()` 共享调用机制防止高频穿透查询。 - **锁机制**:涉及并发写入时,通过 `Acquire()` 实现分布式锁[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值