2013-08-01 3 views
2

Я новичок в Go (как и в последний день), и я играю с простой программой, которая обрабатывает данные из stdin. Я хотел бы сделать так, чтобы, если никакие данные не были предоставлены stdin, тогда программа выведет экран справки и выйдет. Проблема, с которой я столкнулся, заключается в том, что программа, кажется, вешает бесконечно, когда данные не предоставляются через stdin. Вот краткий пример программы и мое предполагаемое использование:Вход файла в golang

package main 

import (
    "fmt" 
    "bufio" 
    "os" 
) 


func main() { 
    scanner := bufio.NewScanner(os.Stdin) 
    scanner.Split(bufio.ScanLines) 
    for scanner.Scan() { 
     str := scanner.Text() 
     fmt.Println(str) 
    } 
} 


Running with input: 
go run test.go < lines.txt 
line1 
line2 
line3 


Running with no input: 
go run test.go 

Второй случай, когда я не обеспечивают ввод является то, что заставляет программу повиснуть. Прочитав документы, мне не ясно, как я смогу закодировать программу, чтобы не ждать ввода бесконечно долго, а скорее разорвать, если ничего не найдено на stdin.

ответ

3

Программа ведет себя точно так же, как говорит код. Код говорит, что он читается из stdin. Ввод в stdin может быть предоставлен путем перенаправления (как вы показываете). Или трубопроводом. Или ... Или пользователь вводит клавиатуру. Было бы очень удивительно, если в последнем случае программа выйдет, прежде чем человек сможет что-то ввести.

Общий подход должен сделать что-то вроде (упрощенный):

var in *os.File 
var err error 

switch name := flag.Arg(0); { 
case name == "": 
     in = os.Stdin 
default: 
     if in, err = os.Open(name); err != nil { 
       log.Fatal(err) 
     } 
} 

Ie. разрешить обрабатывать именованный файл, указанный в качестве аргумента командной строки, - но fallback/default - читать stdin, когда аргумент имени файла не передается программе.

Такой подход играет хорошо с помощью сценариев оболочки, цепочки команд через трубу и т.д.

+0

Имеет смысл. Я несколько ожидал ответа на эти вопросы, но я хотел дважды проверить, что я не просто что-то упустил. – spin77

2

Это может быть немного Strech для вашего USECASE особенно если вы только что взяли идти, но в целом поведение вы хотите мог с помощью выбора с таймаутом:

func scanForInput() chan string{ 
    lines := make(chan string) 
    go func(){ 
     scanner := bufio.NewScanner(os.Stdin) 
     scanner.Split(bufio.ScanLines) 
     for scanner.Scan() { 
      lines <- scanner.Text() 
     } 
     close(lines) 
    } 
    return lines 
} 

func main(){ 
    lines := scanForInput() 
    for { 
    select{ 
     case line, closed := <- lines: 
       fmt.Prinln(line) 
       if closed { 
        return 
       } 
     case time.After(1 * time.Second): 
       printHelpMessage() 
       return 
    } 
    } 
} 

Считайте его источником вдохновения для вашего следующего этапа обучения.

PS: Добро пожаловать, я надеюсь, что язык :-)

+0

Спасибо за отзыв. Похоже, кажется интересным, и я, безусловно, ценю, что у него есть ощущение скриптового языка со скоростью скомпилированного. Я никогда не был полностью продан в OO как особенно эффективная (с точки зрения повторного использования кода) модель кодирования, поэтому мне нравится подход, который они использовали на этом языке. – spin77

+0

Да. Плюс легкий параллелизм. Плюс отличный инструмент. После того, как вы узнаете о том, что наследования нет, это даже нормально для людей ОО. Вам просто нужно принять тот факт, что вам нужно использовать архитектурный проект в стиле Mixin, поскольку диспетчер динамического метода отсутствует. – tike

+1

@flexy: Вы должны удалить внешнюю петлю в функции fun или безумие! – mraaroncruz

Смежные вопросы