使用管道执行go二进制文件时使用scanln

I have the following go code:

package main

import "fmt"

func main() {
    if scanln_test() {
        fmt.Println("Success!")
    }
}

func scanln_test() bool {
    fmt.Print("Please type yes or no and then press enter [y/n]: ")

    var response string
    fmt.Scanln(&response)

    if response == "y" {
        return true
    } else if response == "n" {
        return false
    } else {
        return scanln_test()
    }
}

When execute the compiled binary via pipe, e.g.:

$ echo "just-showing-how-pipe-affects-the-behavior" | ./scanln

I get a infinite output of fmt.Print inside of scanln_test function. However when I don't execute it via pipe, everything works fine.

Is there a way to fix this?

UPD. fmt.Scanln returns "EOF" as an error when the binary executed with in pipe

UPD2. The example with echo above is just to make a point about the pipe, but I'm not looking to read the content of this echo in my go program. The real case looks like this: wget -qO- http://example.com/get | sh -s "param". I have exec of go program inside of this downloaded shell script and I want my program to show dialogue to user with Y/N. I'm not sure whether it's possible at all, so for now I've decided to get rid of the pipe and run it separately like wget -qO- http://example.com/get | sh && go-program "param".

You can use os.ModeCharDevice:

stat, _ := os.Stdin.Stat()

if (stat.Mode() & os.ModeCharDevice) == 0 {
    // piped
    input, _ := ioutil.ReadAll(os.Stdin)
} else {
    // not piped, do whatever, like fmt.Scanln()
}

So you need concurrent input from Stdin (pipe) and user Stdin (Keyboard):
i think you answer is cat command see: How can I pipe initial input into process which will then be interactive?
and: https://en.wikipedia.org/wiki/Cat_(Unix)

see: How to pipe several commands in Go?
and Go Inter-Process Communication

there are 3 things to note:
first: it is good practice to check for all errors:
in your case :

n, err := fmt.Scanln(&response)  

second:
you are using recursive call (Tail Call) and it is not necessary here.
replace it with simple for loop and see: Tail Call Optimization in Go
3rd:
last but not least: in case of bad input your code loops for ever(consuming stack if compiler could not optimizes tail call)!
it is good to limit to 3.
example:

package main

import "fmt"
import "strings"

type Input int

const (
    Timeout Input = iota
    Yes
    No
    Abort
    BadInput
)

func userInput(msg string) Input {
    var input string
    for i := 0; i < 3; i++ {
        fmt.Println(msg)
        n, err := fmt.Scanln(&input)
        if n > 0 {
            switch strings.ToLower(input) {
            case "y":
                return Yes
            case "n":
                return No
            case "a":
                return Abort
            }
        }
        if err != nil {
            return BadInput // or panic(err)
        }
    }
    return Timeout
}
func main() {
    ans := userInput("Please type Yes,No or Abort and then press enter [y/n/a]: ")
    fmt.Println(ans)
    switch ans {
    case Yes:
        fmt.Println("Yes") // do some job
        //...
    }
}

Edit: with this simple "y/n" you do not need to check is it pipe or not.
even simple std Read with one byte slice is good:

os.Stdin.Read(b1)

see my piping sample: https://stackoverflow.com/a/37334984/6169399

but in case your Stdin is pipe you may use:

bytes, err := ioutil.ReadAll(os.Stdin) 

to read all piped data all at once. but be careful to handle errors. you can check if stdin is associated with a terminal or a pipe then use appropriate code.
simple way to detect it is pipe or not :

package main

import (
    "fmt"
    "os"
)

func main() {
    info, err := os.Stdin.Stat()
    if err != nil {
        fmt.Println("not a pipe")
    } else {
        fmt.Println("pipe name=", info.Name(), "pipe size=", info.Size())
    }
}

all in one sample code:

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "strings"
)

type Input int

const (
    Timeout Input = iota
    Yes
    No
    Abort
    BadInput
)

func userInput(msg string) Input {
    var input string
    for i := 0; i < 3; i++ {
        fmt.Println(msg)
        n, err := fmt.Scanln(&input)
        if n > 0 {
            switch strings.ToLower(input) {
            case "y":
                return Yes
            case "n":
                return No
            case "a":
                return Abort
            }
        }
        if err != nil {
            return BadInput // or panic(err)
        }
    }
    return Timeout
}
func main() {
    info, err := os.Stdin.Stat()
    if err != nil {
        //fmt.Println("not a pipe")
        ans := userInput("Please type Yes,No or Abort and then press enter [y/n/a]: ")
        fmt.Println(ans)
        switch ans {
        case Yes:
            fmt.Println("Yes") // do some job
            //...
        }

    } else {
        fmt.Println("pipe name=", info.Name(), "pipe size=", info.Size())
        bytes, err := ioutil.ReadAll(os.Stdin)
        fmt.Println(string(bytes), err) //do some jobe with bytes
    }

}