বিরতিতে পুনরাবৃত্তিমূলক কাজ করার কোনও উপায় আছে কি?


148

গো-তে পুনরাবৃত্তিমূলক পটভূমি কাজ করার কোনও উপায় আছে? আমি Timer.schedule(task, delay, period)জাভা মত কিছু ভাবছি । আমি জানি আমি গোরোটিন দিয়ে এটি করতে পারি এবং Time.sleep()তবে আমি এমন কিছু চাই যা সহজেই বন্ধ হয়ে যায়।

আমি যা পেয়েছি তা এখানে, তবে আমার কাছে কুরুচিপূর্ণ দেখাচ্ছে। কোন ক্লিনার / আরও ভাল উপায় আছে?

func oneWay() {
    var f func()
    var t *time.Timer

    f = func () {
        fmt.Println("doing stuff")
        t = time.AfterFunc(time.Duration(5) * time.Second, f)
    }

    t = time.AfterFunc(time.Duration(5) * time.Second, f)

    defer t.Stop()

    //simulate doing stuff
    time.Sleep(time.Minute)
}

3
সময় ব্যবহার করার জন্য ধন্যবাদ। আপনার উদাহরণে সময়কাল (এক্স) আমি যে উদাহরণটি পেয়েছি তার প্রতিটি হার্ডকোডযুক্ত ইনট রয়েছে এবং আপনি যখন কোন ইনট (বা ভাসা) ভার ব্যবহার করেন এটি অভিযোগ করে।
মাইক গ্রাফ

@ মাইক্রগ্রাফ আপনি t := time.Tick(time.Duration(period) * time.Second)যেখানে করতে পারেন সেখানে সময়কাল হ'লint
ফ্লোরিয়ানরোজেনবার্গ

এই সমাধানটি বেশ ভাল মনে হচ্ছে, আইএমও। ESP। যদি আপনি কেবল বাইরের সময়ের পরিবর্তে f () কল করেন f আপনি যে কাজটি সম্পন্ন করার পরে x সেকেন্ডে কাজ করতে চান সেই ক্ষেত্রে ক্ষেত্রে দুর্দান্ত, একটি ধারাবাহিক বিরতিতে বনাম।
লুক ডাব্লু

উত্তর:


240

ফাংশনটি time.NewTickerএমন একটি চ্যানেল তৈরি করে যা পর্যায়ক্রমিক বার্তা প্রেরণ করে এবং এটি বন্ধ করার জন্য একটি উপায় সরবরাহ করে। এটি এর মতো কিছু ব্যবহার করুন (অরীক্ষিত):

ticker := time.NewTicker(5 * time.Second)
quit := make(chan struct{})
go func() {
    for {
       select {
        case <- ticker.C:
            // do stuff
        case <- quit:
            ticker.Stop()
            return
        }
    }
 }()

আপনি বন্ধ করে কর্মী বন্ধ করতে পারবেন quitচ্যানেল: close(quit)


9
ওপি কী চায় তার উপর নির্ভর করে উত্তরটি ভুল। ওপি যদি পর্যায়ক্রমিক কার্যকর করতে চায় তবে শ্রমিক কতটা সময় ব্যবহার করে না কেন, আপনাকে do stuffএকটি গোটা রুটিনে চালাতে হবে অন্যথায় পরবর্তী কর্মী তাত্ক্ষণিকভাবে মৃত্যুদন্ড কার্যকর করতে হবে (যখন 5 সেকেন্ডের বেশি প্রয়োজন হবে)।
নিমো

2
আইএমও, আপনি close(quit)যখন সময়সূচীটি থামাতে চান ঠিক তখনই আপনার উচিত ।
ডাস্টিন

3
টিকারটি থামানো কাজ করে তবে গুরোটিন কখনই আবর্জনা সংগ্রহ করা যাবে না।
পল হানকিন

4
@SteveBrisk দেখুন ডক । যদি চ্যানেলটি বন্ধ থাকে তবে একটি পঠন সবেমাত্র সফল হবে এবং আপনি এটি চাইবেন না।
নিমো

10
@ বি কে 0, সময় চ্যানেলগুলি "ব্যাকআপ" রাখে না (ডকুমেন্টেশন বলছে "এটি ধীরে ধীরে রিসিভারের জন্য ব্যবস্থাগুলি সামঞ্জস্য করে বা টিক্স টিকিট")। প্রদত্ত কোডটি আপনি যা বলেছেন ঠিক তেমনটি করে (বেশিরভাগ এক টাস্কে চলে); যদি কাজটি দীর্ঘ সময় নেয় তবে পরবর্তী অনুরোধটি কেবল বিলম্বিত হবে; কোনও মিটেক্সের প্রয়োজন নেই। পরিবর্তে যদি এটি কাঙ্ক্ষিত হয় যে প্রতিটি ব্যবধানে একটি নতুন টাস্ক শুরু হয়ে যায় (পূর্ববর্তীটি শেষ না হয়েও) তবে কেবল ব্যবহার করুন go func() { /*do stuff */ }()
ডেভ সি

26

কেমন যেন কিছু

package main

import (
    "fmt"
    "time"
)

func schedule(what func(), delay time.Duration) chan bool {
    stop := make(chan bool)

    go func() {
        for {
            what()
            select {
            case <-time.After(delay):
            case <-stop:
                return
            }
        }
    }()

    return stop
}

func main() {
    ping := func() { fmt.Println("#") }

    stop := schedule(ping, 5*time.Millisecond)
    time.Sleep(25 * time.Millisecond)
    stop <- true
    time.Sleep(25 * time.Millisecond)

    fmt.Println("Done")
}

খেলার মাঠ


3
আপনি নির্ধারিত সময়ে কার্য সম্পাদনকে বনাম ফাঁসির ফাঁকে ফাঁকে ফাঁকে ফাঁকে ফাঁকে রাখা পছন্দ করার time.Tickerচেয়ে একটি ভাল time.After
ডাস্টিন

5
@ ডাস্টিন এবং কাজগুলির শেষ এবং শুরুর মধ্যে একটি নির্দিষ্ট ফাঁক দিয়ে কাজ সম্পাদন করতে চাইলে এটি আরও ভাল। উভয়ই সেরা - এটি দুটি পৃথক ব্যবহারের ক্ষেত্রে।
nos

`` `// এর পরে সময়কাল অপেক্ষা করতে অপেক্ষা করে এবং তারপরে বর্তমান সময়টি // ফেরত চ্যানেলে প্রেরণ করে। // এটি নিউটাইমারের সমান (ঘ) .সি। // অন্তর্নিহিত টাইমার আবর্জনা সংগ্রহকারী দ্বারা পুনরুদ্ধার করা হয়নি // টাইমার আগুন না হওয়া পর্যন্ত। তাহলে দক্ষতা একটি উদ্বেগের বিষয়, ব্যবহার NewTimer `` কীভাবে এই বিবৃতি সম্পর্কে:If efficiency is a concern, use NewTimer
লি

23

আপনি যদি টিক শিফটিংয়ের বিষয়ে যত্নশীল না হন (প্রতিটি মৃত্যুদন্ড কার্যকর করার আগে এটি কত সময় নিয়েছিল তার উপর নির্ভর করে) এবং আপনি চ্যানেলগুলি ব্যবহার করতে চান না, তবে দেশীয় পরিসর ফাংশনটি ব্যবহার করা সম্ভব।

অর্থাত

package main

import "fmt"
import "time"

func main() {
    go heartBeat()
    time.Sleep(time.Second * 5)
}

func heartBeat() {
    for range time.Tick(time.Second * 1) {
        fmt.Println("Foo")
    }
}

খেলার মাঠ


19

এই লাইব্রেরিটি দেখুন: https://github.com/robfig/cron

নীচের হিসাবে উদাহরণ:

c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("@hourly",      func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()

3

এই প্রশ্নের বিস্তৃত উত্তর সম্ভবত ওসামে ব্যবহৃত লেগো ইট পদ্ধতির বিষয়টি বিবেচনা করতে পারে এবং জেসিএসপি এর মাধ্যমে জাভা সম্প্রদায়ের কাছে প্রস্তাব দেওয়া হয়েছিল । এই ধারণাটি নিয়ে পিটার ওয়েলকের একটি খুব ভাল উপস্থাপনা রয়েছে

এই প্লাগ-এন্ড-প্লে অ্যাপ্রোচ সরাসরি গোতে অনুবাদ করে, কারণ গো ওকামের মতো একই যোগাযোগের সিকোয়েন্সিয়াল প্রক্রিয়া ফান্ডামেন্টালগুলি ব্যবহার করে।

সুতরাং, যখন পুনরাবৃত্ত কাজগুলি ডিজাইনের কথা আসে, আপনি আপনার সিস্টেমটিকে সাধারণ উপাদানগুলির একটি ডাটাফ্লো নেটওয়ার্ক হিসাবে তৈরি করতে পারেন (গোরোটাইন হিসাবে) যা চ্যানেলগুলির মাধ্যমে ইভেন্টগুলি বিনিময় করে (যেমন বার্তা বা সংকেত)।

এই পদ্ধতির রচনাটি গঠনমূলক: ছোট ছোট প্রতিটি উপাদানের নিজেরাই বৃহত্তর উপাদান হিসাবে বিজ্ঞাপন হিসাবে কাজ করতে পারে ad এটি খুব শক্তিশালী হতে পারে কারণ জটিল সমবর্তী সিস্টেমগুলি ইটগুলি বোঝার জন্য সহজ থেকে তৈরি।

পাদটীকা: ওয়েলচের উপস্থাপনায় তিনি চ্যানেলগুলির জন্য ওকাম সিনট্যাক্স ব্যবহার করেন, যা ! এবং ? এবং এগুলি সরাসরি ch <- এবং <-ch- in- go এর সাথে মিলে যায়।


3

আমি নিম্নলিখিত কোড ব্যবহার করি:

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    fmt.Println("\nToday:", now)

    after := now.Add(1 * time.Minute)
    fmt.Println("\nAdd 1 Minute:", after)

    for {
        fmt.Println("test")
        time.Sleep(10 * time.Second)

        now = time.Now()

        if now.After(after) {
            break
        }
    }

    fmt.Println("done")
}

এটি আরও সহজ এবং আমার পক্ষে কাজ করে।


0

আপনি যদি কোনও মুহুর্তে টিকারটি থামাতে চান

ticker := time.NewTicker(500 * time.Millisecond)
go func() {
    for range ticker.C {
        fmt.Println("Tick")
    }
}()
time.Sleep(1600 * time.Millisecond)
ticker.Stop()

আপনি যদি এটি বন্ধ করতে না চান তবে টিক দিন :

tick := time.Tick(500 * time.Millisecond)
for range tick {
    fmt.Println("Tick")
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.