英文:
store multiple values in maps
问题
问题:将IP地址和时间存储到计数器中。类似这样的结构:
ip,time,count
然后,我想要能够递增每个IP的计数:
ip++
在我的映射中,然后在给定的时间间隔内,我想要迭代所有的键,并找到时间戳早于N分钟的键。
我需要这样做是为了确保如果客户端断开连接并且我没有正确删除键,我不会在内存中“忘记”一个键。
http://play.golang.org/p/RiWWOCARq7
问题:如何为我存储在映射中的每个IP地址添加时间戳。同时,我需要在多个Go协程中使用它。
我对编程和Golang都很陌生,所以如果这甚至不是正确的方法,如果有人能指点我正确的方向,我将不胜感激。
英文:
problem: Store both an IP address as well as a time to a counter. something like this
ip, time, count
and then i would like to be able to increment the count for each ip:
ip++
in my map, and then on a given interval, i would like to iterate all keys and find the keys with a time stamp older than N minutes.
I need this to make sure i don't "forget" a key in memory if for some reason, client disconnect and i dont delete the key properly.
http://play.golang.org/p/RiWWOCARq7
Question: How do i add a time stamp to every IP address i store in my map. Also i need this be be used across multiple go routines
Im new to both programming and Golang, so if this is not even the correct approach, if anyone could point me in the right direction, i would appreciate it.
答案1
得分: 11
例如,
package main
import (
"sync"
"time"
)
type IPCounter struct {
IPAddr string
Time time.Time
Count int
}
type ipCounterMap struct {
counters map[string]IPCounter
mutex sync.RWMutex
}
var ipCounters = ipCounterMap{counters: make(map[string]IPCounter)}
// 获取IP地址计数器
func Counter(ipAddr string) IPCounter {
ipCounters.mutex.RLock()
defer ipCounters.mutex.RUnlock()
counter, found := ipCounters.counters[ipAddr]
if !found {
counter.IPAddr = ipAddr
}
return counter
}
// 增加IP地址计数器
func Incr(ipAddr string) {
now := time.Now().UTC()
ipCounters.mutex.Lock()
defer ipCounters.mutex.Unlock()
counter, found := ipCounters.counters[ipAddr]
if !found {
counter.IPAddr = ipAddr
}
counter.Time = now
counter.Count++
ipCounters.counters[ipAddr] = counter
}
// 删除IP地址计数器
func Delete(ipAddr string) {
ipCounters.mutex.Lock()
defer ipCounters.mutex.Unlock()
delete(ipCounters.counters, ipAddr)
}
// 获取旧的IP地址计数器
func OldIPCounters(old time.Duration) []IPCounter {
var counters []IPCounter
oldTime := time.Now().UTC().Add(-old)
ipCounters.mutex.RLock()
defer ipCounters.mutex.RUnlock()
for _, counter := range ipCounters.counters {
if counter.Time.Before(oldTime) {
counters = append(counters, counter)
}
}
return counters
}
func main() {}
英文:
For example,
package main
import (
"sync"
"time"
)
type IPCounter struct {
IPAddr string
Time time.Time
Count int
}
type ipCounterMap struct {
counters map[string]IPCounter
mutex sync.RWMutex
}
var ipCounters = ipCounterMap{counters: make(map[string]IPCounter)}
// Get IP address counter
func Counter(ipAddr string) IPCounter {
ipCounters.mutex.RLock()
defer ipCounters.mutex.RUnlock()
counter, found := ipCounters.counters[ipAddr]
if !found {
counter.IPAddr = ipAddr
}
return counter
}
// Increment IP address counter
func Incr(ipAddr string) {
now := time.Now().UTC()
ipCounters.mutex.Lock()
defer ipCounters.mutex.Unlock()
counter, found := ipCounters.counters[ipAddr]
if !found {
counter.IPAddr = ipAddr
}
counter.Time = now
counter.Count++
ipCounters.counters[ipAddr] = counter
}
// Delete IP address counter
func Delete(ipAddr string) {
ipCounters.mutex.Lock()
defer ipCounters.mutex.Unlock()
delete(ipCounters.counters, ipAddr)
}
// Get old IP address counters old durations ago
func OldIPCounters(old time.Duration) []IPCounter {
var counters []IPCounter
oldTime := time.Now().UTC().Add(-old)
ipCounters.mutex.RLock()
defer ipCounters.mutex.RUnlock()
for _, counter := range ipCounters.counters {
if counter.Time.Before(oldTime) {
counters = append(counters, counter)
}
}
return counters
}
func main() {}
答案2
得分: 5
你可能想要一个ip -> struct { ip, counter, lastTime }的映射表,这样你就可以通过ip查找计数器并更新它。
var Counters = map[string]*Counter{}
type Counter struct {
ip string
count int
lastTime time.Time
}
这里有一个在Playground上的可工作示例:http://play.golang.org/p/TlCTc_4iq5
添加"find older than"的功能只需遍历映射表的值,与当前时间进行比较,当时间足够旧时执行相应操作。
英文:
You probably want a map of ip -> struct { ip, counter, lastTime }
that way, you can look up the counter by ip and then update it
var Counters = map[string]*Counter{}
type Counter struct {
ip string
count int
lastTime time.Time
}
Here's a working example on Play http://play.golang.org/p/TlCTc_4iq5
Adding the find older than is simply range over the values of the map comparing to now and do something when it's old enough.
答案3
得分: 2
看起来你需要一个struct
(结构体)。map
(映射)用于存储所有键都是一种类型,而所有元素都是另一种(或相同的)类型的集合。
用于分组不同数据类型的相关变量的集合时,可以使用struct
。
例如:
type IPCounter struct {
ip string
time time.Time
count int
}
这是一些示例代码,创建了一个这样的对象并增加了计数:
package main
import (
"fmt"
"time"
)
type IPAddressCounter struct {
ip string
time time.Time
count int
}
func (i *IPAddressCounter) IncrementCount() {
i.count++
}
func makeCounter(ip string) IPAddressCounter {
return IPAddressCounter{
ip: ip,
time: time.Now(),
}
}
func main() {
mapOfIPCounters := make(map[string]IPAddressCounter)
mapOfIPCounters["192.168.1.1"] = makeCounter("192.168.1.1")
mapOfIPCounters["192.168.1.2"] = makeCounter("192.168.1.2")
mapOfIPCounters["192.168.1.3"] = makeCounter("192.168.1.3")
for key, value := range mapOfIPCounters {
value.IncrementCount()
mapOfIPCounters[key] = value
fmt.Println("The counter for "+key+" is", mapOfIPCounters[key].count)
}
}
希望对你有帮助!
英文:
It sounds like you need a struct. A map is for storing a collection where all the keys are of one type and all the elements are of another (or the same type).
For grouping a collection of variables of different data types, that are related, use a struct
e.g.
type IPCounter struct {
ip string
time time.Time
count int
}
Here's some sample code that creates one of these objects and increments the count:
package main
import (
"fmt"
"time"
)
type IPAddressCounter struct {
ip string
time time.Time
count int
}
func (i *IPAddressCounter) IncrementCount() {
i.count++
}
func makeCounter(ip string) IPAddressCounter {
return IPAddressCounter{
ip: ip,
time: time.Now(),
}
}
func main() {
mapOfIPCounters := make(map[string]IPAddressCounter)
mapOfIPCounters["192.168.1.1"] = makeCounter("192.168.1.1")
mapOfIPCounters["192.168.1.2"] = makeCounter("192.168.1.2")
mapOfIPCounters["192.168.1.3"] = makeCounter("192.168.1.3")
for key, value := range mapOfIPCounters {
value.IncrementCount()
mapOfIPCounters[key] = value
fmt.Println("The counter for "+key+" is", mapOfIPCounters[key].count)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论