# 函数参数

函数名后面的小括号内放置参数，参数后面需要加冒号再加类型，一般函数的参数的数量是固定的。闭包的参数的两个竖线中间。宏看起来像函数，但在名称后面有感叹号，后面括号里面的参数数量可以不是固定的。

参数的类型可以是具体类型，也可以是泛型，还可以是 impl Trait 的形式。

在结构体的 impl 内部，如果定义的函数参数不包含 self (如 self, &self, &mut self)，就是静态方法，需要使用 StructName::method 调用，如 String::from()， 如果有包含 self 为参数的函数，就是实例方法。 如 "Hello".to_string() 。

带有泛型和生命周期的函数参数相对复杂，但只要多看，熟悉了就好了。看得多了，很多时候只需浏览一个函数的签名，就可以知道该函数大部分的行为。譬如如下函数签名：

```rust
// add 函数，left hand side 参数类型 i32, righ hand side 参数类型 i32, 返回 i32 类型 
fn add(lhs: i32, rhs: i32) -> i32 {}
```

```rust
fn play_with(dog_name: String, game_name: String) {}
```

```rust
struct Dog;
struct Game;
fn play_with(dog: Dog, game: Game);
```

```rust
fn foo<T>(input: &mut T, val: T) {}
```

```rust
fn do_stuff<T: Clone>(value: &T) {}

// 上面这行等效于

fn do_stuff(value: &T)
where T: Clone
{}
```


其它：
```rust

fn print<'a>(s: &'a str);

fn get_str() -> &str;

fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command

fn new(calculation: T) -> Cacher<T>
where T: Fn(u32) -> u32,
{}

fn tokenize<'a>(code: &'a str) -> impl Iterator<Item=&'a str> {}

async fn main() -> Result<(), std::io::Error> {}

```


如下函数签名解读错误的是：

```rust
async fn handle_request(request: HttpRequest) -> HttpResponse {}
```

## 答案

它有两个参数

## 选项

### 

从 async 看出这是一个异步函数 

### 

函数名是 handle_request

### 

参数名是 request, 参数类型是 HttpRequest

###

返回类型是 HttpResponse

