在地图中存储多个值

huangapple go评论74阅读模式
英文:

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)
	}

}

huangapple
  • 本文由 发表于 2014年7月20日 17:53:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/24849310.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定