有关Go中频道方向和阻塞的困惑

In a function definition, if a channel is an argument without a direction, does it have to send or receive something?

func makeRequest(url string, ch chan<- string, results chan<- string) {
    start := time.Now()

    resp, err := http.Get(url)
    defer resp.Body.Close()
    if err != nil {
        fmt.Printf("%v", err)
    }

    resp, err = http.Post(url, "text/plain", bytes.NewBuffer([]byte("Hey")))
    defer resp.Body.Close()

    secs := time.Since(start).Seconds()

    if err != nil {
        fmt.Printf("%v", err)
    }
    // Cannot move past this.
    ch <- fmt.Sprintf("%f", secs) 
    results <- <- ch
}

func MakeRequestHelper(url string, ch chan string, results chan string, iterations int) {
    for i := 0; i < iterations; i++ {
        makeRequest(url, ch, results)
    }
    for i := 0; i < iterations; i++ {
        fmt.Println(<-ch)
    }
}

func main() {
    args := os.Args[1:]
    threadString := args[0]
    iterationString := args[1]
    url := args[2]
    threads, err := strconv.Atoi(threadString)
    if err != nil {
        fmt.Printf("%v", err)
    }
    iterations, err := strconv.Atoi(iterationString)
    if err != nil {
        fmt.Printf("%v", err)
    }

    channels := make([]chan string, 100)
    for i := range channels {
        channels[i] = make(chan string)
    }

    // results aggregate all the things received by channels in all goroutines
    results := make(chan string, iterations*threads)

    for i := 0; i < threads; i++ {
        go MakeRequestHelper(url, channels[i], results, iterations)

    }

    resultSlice := make([]string, threads*iterations)
    for i := 0; i < threads*iterations; i++ {
        resultSlice[i] = <-results
    }
}

In the above code,

ch <- or <-results

seems to be blocking every goroutine that executes makeRequest.

I am new to concurrency model of Go. I understand that sending to and receiving from a channel blocks but find it difficult what is blocking what in this code.

I'm not really sure that you are doing... It seems really convoluted. I suggest you read up on how to use channels.

https://tour.golang.org/concurrency/2

That being said you have so much going on in your code that it was much easier to just gut it to something a bit simpler. (It can be simplified further). I left comments to understand the code.

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "sync"
    "time"
)

// using structs is a nice way to organize your code
type Worker struct {
    wg        sync.WaitGroup
    semaphore chan struct{}
    result    chan Result
    client    http.Client
}

// group returns so that you don't have to send to many channels
type Result struct {
    duration float64
    results  string
}

// closing your channels will stop the for loop in main
func (w *Worker) Close() {
    close(w.semaphore)
    close(w.result)
}

func (w *Worker) MakeRequest(url string) {
    // a semaphore is a simple way to rate limit the amount of goroutines running at any single point of time
    // google them, Go uses them often
    w.semaphore <- struct{}{}
    defer func() {
        w.wg.Done()
        <-w.semaphore
    }()

    start := time.Now()

    resp, err := w.client.Get(url)
    if err != nil {
        log.Println("error", err)
        return
    }
    defer resp.Body.Close()

    // don't have any examples where I need to also POST anything but the point should be made
    // resp, err = http.Post(url, "text/plain", bytes.NewBuffer([]byte("Hey")))
    // if err != nil {
    // log.Println("error", err)
    // return
    // }
    // defer resp.Body.Close()

    secs := time.Since(start).Seconds()

    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Println("error", err)
        return
    }
    w.result <- Result{duration: secs, results: string(b)}
}

func main() {
    urls := []string{"https://facebook.com/", "https://twitter.com/", "https://google.com/", "https://youtube.com/", "https://linkedin.com/", "https://wordpress.org/",
        "https://instagram.com/", "https://pinterest.com/", "https://wikipedia.org/", "https://wordpress.com/", "https://blogspot.com/", "https://apple.com/",
    }

    workerNumber := 5
    worker := Worker{
        semaphore: make(chan struct{}, workerNumber),
        result:    make(chan Result),
        client:    http.Client{Timeout: 5 * time.Second},
    }

    // use sync groups to allow your code to wait for
    // all your goroutines to finish
    for _, url := range urls {
        worker.wg.Add(1)
        go worker.MakeRequest(url)
    }

    // by declaring wait and close as a seperate goroutine
    // I can get to the for loop below and iterate on the results
    // in a non blocking fashion
    go func() {
        worker.wg.Wait()
        worker.Close()
    }()

    // do something with the results channel
    for res := range worker.result {
        fmt.Printf("Request took %2.f seconds.
Results: %s

", res.duration, res.results)
    }
}

The channels in channels are nil (no make is executed; you make the slice but not the channels), so any send or receive will block. I'm not sure exactly what you're trying to do here, but that's the basic problem.

See https://golang.org/doc/effective_go.html#channels for an explanation of how channels work.